Эполл с событием, вызванным краем

Справочная страницаEpoll имеет пример кода для фронта, срабатывающего следующим образом:

for (;;) {
    nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
    if (nfds == -1) {
        perror("epoll_pwait");
        exit(EXIT_FAILURE);
    }

    for (n = 0; n < nfds; ++n) {
        if (events[n].data.fd == listen_sock) {
            conn_sock = accept(listen_sock,
                        (struct sockaddr *) &local, &addrlen);
            if (conn_sock == -1) {
                perror("accept");
                exit(EXIT_FAILURE);
            }
            setnonblocking(conn_sock);
            ev.events = EPOLLIN | EPOLLET;
            ev.data.fd = conn_sock;
            if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock,
                    &ev) == -1) {
                perror("epoll_ctl: conn_sock");
                exit(EXIT_FAILURE);
            }
        } else {
            do_use_fd(events[n].data.fd);
        }
    }
}

В функции do_use_fd я вызываю неблокированный recv в цикле while до EAGAIN, пример кода работает нормально.

У меня есть вопрос по поводу этого примера кода, предположим, что теперь у меня есть 50 подключений клиентов сокетов, внезапно 10 клиентов записывают данные одновременно, поэтому epoll_wait () вернет 10 и затем перейдет к циклу:

for (n = 0; n < nfds; ++n)

это позвонитdo_use_fd(events[n].data.fd); для этих 10 клиентов, предположим, что n = 5 выполнено, а n = 6 еще не завершено, внезапно описание файла события n = 3 получит новые данные, после того как все эти 10 событий будут выполнены, и я вернусь к epoll_wait. получить событие сообщить мне, что у клиента есть новые данные для чтения? или я пропущу это, потому что когда событие произошло, код не в epoll_wait !!

 jww12 окт. 2018 г., 00:03

Ответы на вопрос(2)

когда вы используете Edge Triggered под epoll, прочитайте что-нибудь, может вот так >>>

int n = -1;
while (1)
{
    n = recv(fd, iobuf, init_buff_size, MSG_DONTWAIT);
    if (n > 0)
    {
        LOG(glogfd, LOG_TRACE, "fd[%d] recv len %d\n", fd, n);
        mybuff_setdata(&(curcon->recv_buff), iobuf, n); // this is my func
        if (n == init_buff_size)
        {
            LOG(glogfd, LOG_DEBUG, "fd[%d] need recv nextloop %d\n", fd, n);
            continue;
        }
        break;
    }
    if (n == 0)
    {
        LOG(glogfd, LOG_ERROR, "fd[%d] close %s:%d!\n", fd, ID, LN);
        return do_close(fd);
    }
    if (errno == EINTR)
    {
        LOG(glogfd, LOG_TRACE, "fd[%d] need recv again!\n", fd);
        continue;
    }
    else if (errno == EAGAIN)
    {
        LOG(glogfd, LOG_TRACE, "fd[%d] need recv next!\n", fd);
        modify_fd_event(fd, EPOLLIN);   // this is the KEY, add read again
        break;
    }
    else
    {
        LOG(glogfd, LOG_ERROR, "fd[%d] close %s:%d!\n", fd, ID, LN);
        return do_close(fd);
    }
}
 ByteMe9527 дек. 2018 г., 16:30
 modify_fd_event (fd, EPOLLIN); Вам на самом деле не нужно перерегистрировать это, не так ли?
Решение Вопроса

Пока вы читаете, пока не получитеEAGAIN ошибка, вы получите событие при следующем вызове.epoll_wait

Событие запускается только при изменении между пустым и непустым (или полным и не полным дляEPOLLOUT), но этот статус сохраняется до тех пор, пока событие не будет доставлено через.epoll_wait

На несколько связанных примечание: если вы регистрируетесь дляEPOLLIN а такжеEPOLLOUT Если вы не заполняете буфер отправки, вы все равно получаетеEPOLLOUT флаг, установленный в событии, возвращаемомepoll_wait каждый разEPOLLIN срабатывает - см.https://lkml.org/lkml/2011/11/17/234 для более подробного объяснения.

И, наконец, точное поведение режима с триггером на самом деле зависит от типа используемого сокета и не являетсядействительно задокументировано где угодно. Некоторое время назад я провел несколько тестов и задокументировал свои выводы:http://cmeerw.org/blog/753.html#753 - короче говоря, для сокетов дейтаграмм вы можете получить больше событий, чем ожидаете.

 barfatchen16 окт. 2012 г., 01:52
Спасибо, cmeerw, вы очень помогли!
 Damon15 окт. 2012 г., 16:41
... и дляeventfdс иtimerfdты получаешь меньше чем тыбуду ожидать.

Ваш ответ на вопрос