У меня есть два файловых дескриптора, один файловый дескриптор чтения на конвейере и другой дескриптор подключения к сокету. Ни один из них не является неблокирующим. Оба они добавляются в контекст epoll одним событием EPOLLIN. Наконец, я вызываю epoll_wait с таймаутом = -1. Ниже приведен пример кода. У меня два вопроса: -

  1. Дескрипторы каналов и соединений должны быть неблокирующими. Это не срабатывает по фронту. Если да, то это хорошая практика или обязательно, а если обязательно, то почему?

  2. Я устанавливаю тайм-аут на -1, но epoll_wait немедленно возвращает значение 0. Почему это происходит? с тайм-аутом -1, epoll_wait должен возвращать значение только при наличии события.

    int total_fd_ready = -1;
    struct epoll_event pipe_event, connection_event, total_events[64];
    
    pipe_event.data.fd = pipe_fd[0];
    piple_event.events = EPOLLIN;
    connection_event.data.fd = conn_fd;
    connection_event.events = EPOLLIN;
    
    total_fd_ready = Epoll_wait(epoll_fd, total_events, 64, -1);
     printf("%d\n", total_fd_ready);
    

    Epoll_wait определяется как

    int Epoll_wait(int e_fd, struct epoll_event *events, int max_events, int timeout)
    {
    #ifdef DBG
            printf("Epoll_wait called on epoll_fd: %d with max_events: %d and timeout: %d\n", e_fd, max_events, timeout);
    #endif
    
    int result = -1;
    if(result = (epoll_wait(e_fd, events, max_events, timeout)) < 0)
            if(errno != EINTR)
                    err_sys("epoll_wait error with epoll fd: %d and timeout : %d\n", e_fd, timeout);
            #ifdef DBG
            else
                    printf("epoll_wait was interrupted\n");
            #endif
    return result;
    }
    

ОБНОВЛЕНИЕ: обнаружил проблему, хотя я не могу объяснить, почему для результата установлено значение 0. Мне нужны наручники в следующем операторе if

 if((result = (epoll_wait(e_fd, events, max_events, timeout))) < 0)
0
Jimm 24 Дек 2012 в 07:55
Как вы объявляете и инициализируете total_events?
 – 
Some programmer dude
24 Дек 2012 в 08:06
Обновил код этим
 – 
Jimm
24 Дек 2012 в 08:07
И если были скомпилированы с включенными предупреждениями, например с gcc -Wall компилятор предупредил бы вас соответствующим образом
 – 
Basile Starynkevitch
24 Дек 2012 в 10:55

1 ответ

Лучший ответ

Ответ заключается в том, что оператор сравнения < имеет более высокий приоритет, чем присваивание, что означает, что result присваивается результат выражения (epoll_wait(e_fd, events, max_events, timeout)) < 0.

4
Some programmer dude 24 Дек 2012 в 08:11
Ах, это имеет смысл, спасибо !! Знаете ли вы, нужно ли мне сделать мои файловые дескрипторы неблокирующими для работы epoll? Я не понимаю, почему для сценариев с запуском по фронту дескрипторы файлов должны быть неблокирующими
 – 
Jimm
24 Дек 2012 в 08:12
Поскольку вы не знаете, будет ли ваш следующий вызов read(2) блокироваться, полностью нарушая природу мультиплексирования epoll(7).
 – 
Nikolai Fetissov
24 Дек 2012 в 08:17
Зачем вызывать блок чтения, если epoll вернул дескриптор сокета с событием EPOLLIN? Обычно я регистрирую fd сокета для события чтения, а затем, когда возвращается epoll_wait, я проверяю, является ли сокет fd частью «событий», и если это так, то он не должен блокироваться. Даже при нулевом тайм-ауте можно было бы проверить, содержат ли возвращенные «события» сокет для чтения.
 – 
Jimm
24 Дек 2012 в 08:18
При настройке с запуском по фронту вы должны читать, пока не получите EAGAIN, а это невозможно с дескриптором блокировки.
 – 
Nikolai Fetissov
24 Дек 2012 в 08:20
Где это обязательно? EAGAIN имеет дело с неблокирующим аспектом чтения. На самом деле, у меня есть рабочий пример с блокировкой чтения и срабатывания фронта. Я знаю размер данных, которые я должен прочитать, скажем, 1 КБ. если чтение возвращает частичные данные, я просто читаю частичные данные и жду, пока epoll_wait снова сделает их доступными для чтения.
 – 
Jimm
24 Дек 2012 в 08:25