события tty в очереди epoll после закрытия fd 0

рассмотрим следующий случай:

  • событие EPOLLIN зарегистрировано для fd 0 (stdin)
  • событие EPOLLIN генерируется для fd 0 и неявно ставится в очередь для чтения в epoll
  • fd 0 закрыт (и EPOLL_CTL_DELeted) перед вызовом epoll_wait()
  • epoll_wait() вызывается для чтения событий в очереди

Сейчас:

  • если стандартный ввод является терминалом, при вызове epoll_wait() будет сообщено о событии EPOLLIN из шага 2.
  • если стандартный ввод является не терминалом, а каналом, событие EPOLLIN из шага 2 не будет сообщено

Почему случай tty отличается?

Программа испытаний:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>

struct epoll_event event1 = {
    .events = EPOLLIN,
    .data = { .fd = 0}
};

int main(int argc, char **argv)
{
    int epfd = epoll_create(1);
    int rc;
    epoll_ctl(epfd, EPOLL_CTL_ADD, 0, &event1);
    sleep(2); //allow meself time to type false\n
    printf("closing stdin ...\n");
    close(0);
    //even if i remove it explicitly the event will be found in the que after
    epoll_ctl(epfd, EPOLL_CTL_DEL, 0, &event1);
    printf("gathering events ...\n");
    event1.events = 0;
    event1.data.fd = -1;
    rc = epoll_wait(epfd, &event1, 1, 0);
    switch(rc) {
        case 1:
            printf("event received: event=%d on fd %d\n", event1.events, event1.data.fd);
            break;
        case 0:
            printf("no events received");
            break;
        case -1:
            printf("epoll_wait error\n");
            break;
        default:
            printf("weird event count %d\n", rc);
    }

    return 0;
}

запуск программы с помощью stdin из tty:

[root@tinkerbell src]# ./epolltest 
false
closing stdin ...
gathering events ...
event received: event=1 on fd 0
[root@tinkerbell src]# false
[root@tinkerbell src]# 

запуск программы с помощью стандартного ввода из канала:

[root@tinkerbell src]# cat t.sh
#!/bin/bash

echo "bah";
sleep 10;
[root@tinkerbell src]# ./t.sh | ./epolltest 
closing stdin ...
gathering events ...
no events received[root@tinkerbell src]# 

person user237419    schedule 23.01.2014    source источник


Ответы (1)


другой вопрос, но ответ можно применить и здесь

События, перехваченные epoll, поступают из файла*, поскольку это абстракция, которую обрабатывает ядро. События действительно происходят в файле*, и если вы выполняете дублирование() 1000 раз для одного fd, нельзя сказать, что события для fd = 122.

person user237419    schedule 23.01.2014