epoll_wait setzt immer das EPOLOUT-Bit?

Lesezeit: 4 Minuten

An einer Abhörbuchse habe ich die eingestellt EPOLLIN Bit aber auf Clientverbindungen habe ich gesetzt EPOLLIN | EPOLLOUT bisschen zu struct epoll_event so:

struct epoll_event ev;

ev.data.fd = fd;
ev.events = EPOLLIN | EPOLLOUT;
if (epoll_ctl(evs->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0)
     ...

Und so teste ich Bits:

if ((events & EPOLLIN) == EPOLLIN)
     ...
if ((events & EPOLLOUT) == EPOLLOUT)
     ...

Ich habe auch versucht, wie:

if (events & EPOLLIN)
     ...
if (events & EPOLLOUT)
     ...

Beide Wege sind IMMER wahr!

Wenn ich jedoch epoll_wait auf meinem epoll fd aufrufe, hat der zurückgegebene aktive Dateideskriptor IMMER beide Bits gesetzt, obwohl send() EAGAIN nicht zurückgegeben hat, aber wenn ich recv() versuche, gibt es EAGAIN zurück.

Ich habe keine Ahnung, was ich tun soll, wenn recv() EAGAIN zurückgibt, soll ich die entfernen EPOLLOUT Flagge oder was?

Mehr Code wie von @Nikolai N Fetissov angefordert:

static int get_active_fd(events *evs, int index, sstate_t *flags)
{
    uint32_t events = evs->events[index].events;
    int fd = evs->events[index].data.fd;;

    if ((events & EPOLLERR) == EPOLLERR || (events & EPOLLHUP) == EPOLLHUP) {
        close(fd);
        return -1;
    }

    if (events & EPOLLIN)
        *flags |= DATA_IN;

    return fd;
}

void sockset_add(events *evs, int fd)
{
    struct epoll_event ev;
    ...
    ev.data.fd = fd;
    ev.events = EPOLLIN;
    if (epoll_ctl(evs->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0)
        eprintf("sockset_add(): epoll_ctl(%d) returned an error %d(%s)\n",
                fd, errno, strerror(errno));
}

Dann später, wo ich epoll_wait() aufrufe:

if (flags & DATA_IN) {
       /* try to read which is impossible because this is never set.  */

Benutzer-Avatar
Nikolai Fetissov

Ich glaube, du hast es falsch verstanden. Nicht einschließen EPOLLOUT es sei denn du hast EAGAIN von einem Schreibversuch und entfernen Sie es, wenn Sie Bytes erfolgreich in einen Socket geschrieben haben.

Dies bedeutet im Grunde, dass Socket ist stets beschreibbar, solange im Kernel-Sendepuffer des Sockets Platz ist.

Bearbeiten 0:

Sie haben zwei Datenströme – Eingang und Ausgang.

Sie warten auf die Eingabe durch Einschließen EPOLLIN in den Fahnen. Wenn bei der Rückkehr von epoll_wait(2) Wenn dieses Flag nicht gesetzt ist, ist entweder ein Ereignis auf einem anderen Socket aufgetreten oder dieser Socket hatte ein anderes Ereignis. Belassen Sie das Flag in den Ereignissen, es sei denn, Sie erhalten einen Fehler (was bedeutet, dass Sie immer noch an der Eingabe auf dem Socket interessiert sind).

Sie müssen nicht auf die Ausgabe warten (da es Ihre Aktion ist), Sie schreiben einfach in den Socket, aber wenn Sie den Socket-Sendepuffer überlaufen, erhalten Sie EAGAIN aus send(2) oder write(2). In diesem Fall warten Sie darauf, dass die Ausgabe möglich ist (Socket-Sendepuffer wird geleert, wodurch Platz für Sie geschaffen wird, um mehr zu senden), indem Sie es einschließen EPOLLOUT. Sobald Sie das erhalten haben, schreiben Sie Ihre ausstehenden Ausgangsbytes in den Socket und entfernen Sie sie, wenn Sie erfolgreich sind EPOLLOUT aus den Veranstaltungen.

Jetzt EPOLLET zeigt an flankengesteuert warten, was bedeutet, dass Ihr gewünschtes Ereignis nur einmal pro Zustandsänderung signalisiert wird (z. B. von “keine Eingabe” auf “Eingabe vorhanden”). In diesem Modus sollen Sie Eingabebytes in einer Schleife lesen, bis Sie erhalten EAGAIN.

Hoffe das hilft.

  • Ich habe das Bit entfernt, aber immer noch getestet, ob die Bit-Ergebnisse wahr sind

    Benutzer1551592

    26. November 2012 um 16:39 Uhr


  • Ich meine, wenn ich EPOLOUT entferne und auf EPOLLIN teste, würde es fehlschlagen, was äußerst verwirrend ist

    Benutzer1551592

    26. November 2012 um 16:53 Uhr

  • Das ist, was ich sage – Sie sind verwirrt, also zeigen Sie, wie Sie Deskriptoren für Umfragen einrichten und Umfrageergebnisse testen. Irgendwo da ist die Verwechslung.

    – Nikolai Fetissov

    26. November 2012 um 16:57 Uhr

  • Okay, lassen Sie mich raten, brauche ich EPOLLET, um EPOLOUT zu ersetzen, wenn keine Daten geschrieben werden müssen (auch bekannt als wenn send() EAGAIN nicht zurückgibt)? EDIT: Mehr Code jetzt hinzugefügt.

    Benutzer1551592

    26. November 2012 um 16:58 Uhr


  • @user9000 Wenn Sie Daten lesen möchten, setzen Sie EPOLLIN und lesen Sie Daten, wenn es true zurückgibt, wenn das Lesen EAGAIN zurückgibt, warten Sie bis zum nächsten Mal. Wenn Sie Daten zu senden haben, senden Sie sie. Wenn das Senden EAGAIN und/oder EWOULDBLOCK zurückgibt, schalten Sie EPOLOUT ein und setzen das Senden fort, wenn EPOLOUT wahr wird. Wenn Sie nichts zu senden haben, deaktivieren Sie EPOLOUT. In Ihrem Code ist es jedoch schwierig zu erkennen, welche Bits Sie in welchen Strukturen überprüfen. Sie sollten wahrscheinlich den Code anzeigen, der epoll_wait() ausführt. EPOLLET ist schwer richtig zu machen, ich würde Ihnen raten, es nicht zu verwenden, bis Sie epoll absolut 100% vollständig verstanden haben.

    – Nr

    26. November 2012 um 17:13 Uhr


1074570cookie-checkepoll_wait setzt immer das EPOLOUT-Bit?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy