Linux 当其他进程关闭fifo时,无法从epoll_wait唤醒

Linux 当其他进程关闭fifo时,无法从epoll_wait唤醒,linux,select,multiprocessing,fifo,epoll,Linux,Select,Multiprocessing,Fifo,Epoll,我在两个不同的二进制文件中看到了不同的epoll和select行为,希望得到一些调试帮助。在下文中,epoll\u wait和select将互换使用 我有两个进程,一个编写器和一个读取器,它们通过fifo进行通信。读卡器执行epoll\u wait以收到写入通知。我还想知道写入程序何时关闭fifo,而且epoll_wait似乎也应该通知我这一点。以下玩具程序的行为与预期一致,说明了我试图实现的目标: #include <errno.h> #include <fcntl.h>

我在两个不同的二进制文件中看到了不同的
epoll
select
行为,希望得到一些调试帮助。在下文中,
epoll\u wait
select
将互换使用

我有两个进程,一个编写器和一个读取器,它们通过fifo进行通信。读卡器执行
epoll\u wait
以收到写入通知。我还想知道写入程序何时关闭fifo,而且
epoll_wait
似乎也应该通知我这一点。以下玩具程序的行为与预期一致,说明了我试图实现的目标:

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/stat.h>
#include <unistd.h>

int
main(int argc, char** argv)
{
  const char* filename = "tempfile";
  char buf[1024];
  memset(buf, 0, sizeof(buf));

  struct stat statbuf;
  if (!stat(filename, &statbuf))
    unlink(filename);

  mkfifo(filename, S_IRUSR | S_IWUSR);

  pid_t pid = fork();
  if (!pid) {
    int fd = open(filename, O_WRONLY);
    printf("Opened %d for writing\n", fd);
    sleep(3);
    close(fd);
  } else {
    int fd = open(filename, O_RDONLY);
    printf("Opened %d for reading\n", fd);

    static const int MAX_LENGTH = 1;
    struct epoll_event init;
    struct epoll_event evs[MAX_LENGTH];
    int efd = epoll_create(MAX_LENGTH);

    int i;
    for (i = 0; i < MAX_LENGTH; ++i) {
        init.data.u64 = 0;
        init.data.fd = fd;
        init.events |= EPOLLIN | EPOLLPRI | EPOLLHUP;
        epoll_ctl(efd, EPOLL_CTL_ADD, fd, &init);
    }

    while (1) {
      int nfds = epoll_wait(efd, evs, MAX_LENGTH, -1);
      printf("%d fds ready\n", nfds);
      int nread = read(fd, buf, sizeof(buf));
      if (nread < 0) {
        perror("read");
        exit(1);
      } else if (!nread) {
        printf("Child %d closed the pipe\n", pid);
        break;
      }
      printf("Reading: %s\n", buf);
    }
  }
  return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int
主(内部argc,字符**argv)
{
const char*filename=“tempfile”;
char-buf[1024];
memset(buf,0,sizeof(buf));
结构stat statbuf;
如果(!stat(filename,&statbuf))
取消链接(文件名);
mkfifo(文件名,S|u IRUSR | S|u IWUSR);
pid_t pid=fork();
如果(!pid){
int fd=打开(仅文件名为O_);
printf(“打开%d以便写入”,fd);
睡眠(3);
关闭(fd);
}否则{
int fd=打开(仅文件名);
printf(“打开%d以便读取”,fd);
静态常数int MAX_LENGTH=1;
结构epoll_事件初始化;
结构epoll_事件evs[最大长度];
int efd=epoll\u create(最大长度);
int i;
对于(i=0;i
然而,当我使用另一个阅读器(我没有权限发布它的代码,但它会发出完全相同的调用——玩具程序就是在它上面建模的)执行此操作时,当编写器关闭fifo时,该过程不会唤醒。玩具阅读器还通过
select
提供所需的语义。配置为使用
select
的真实读卡器也会失败

什么可以解释这两种行为的不同?对于任何提供的假设,我如何验证它们?我正在运行Linux2.6.38.8。

是一个很好的工具,可以确认系统调用被正确调用(即参数被正确传递,并且不会返回任何意外错误)

除此之外,我建议使用来检查是否没有其他进程仍然打开FIFO。

对于(非常)迟的响应表示歉意。fifo确实是开放的,lsof帮助我看到了这一点。