是否可以将事件文件描述符与中断驱动输入结合使用?

Is it possible to use event file descriptor in combination with interrupt-driven input?

这是最小的示例(有意忽略了错误检查和信号安全):

#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/eventfd.h>
#include <stdio.h>
#include <sys/wait.h>

void reader(int a)
{
  printf("hello!\n");
  wait(NULL);
  exit(EXIT_SUCCESS);
}

int main()
{
  signal(SIGIO, reader);
  int efd = eventfd(0, EFD_NONBLOCK);
  fcntl(efd, F_SETOWN, getpid());
  int flags;
  flags= fcntl(efd, F_GETFL);
  fcntl(efd, F_SETFL, flags | O_ASYNC);

  pid_t p = fork();
  if (p)
  {
    for(;;)
      pause();
  }
  else 
  {
    uint64_t buff = 1;
    if (write(efd, &buff, sizeof(buff)) == -1)
      printf("write error\n");
    exit(EXIT_SUCCESS);
  }
}

这段代码应该在子进程写入事件文件描述符后在父进程中生成 SIGIO,但实际上并没有。我什至尝试从 eventfd 系统调用中删除 EFD_NONBLOCK 并且我有相同的行为。所以这里有几个问题。

这是处理中断驱动的正确方法吗I/O?

中断驱动 I/O 能否与事件文件描述符结合使用?如何结合使用?

调用 eventfd() 返回的文件描述符与通过调用 write() 更改内容时生成信号无关。

如果想让parent每次唤醒文件描述符,一个8字节的值。被写入,然后让父级使用 select(),其中输入变量包含从调用 eventfd().

返回的文件描述符

eventfd() 的 linux 手册页包含如何使用 eventfd() 函数的示例。

select() 的 linux 手册页包含如何使用 select() 函数的示例。

eventfd 文件描述符不支持 O_ASYNC 标志。

似乎 man open(2) 描述了 当前 O_ASYNC 功能的所有实现者:

This feature is available only for terminals, pseudoterminals, sockets, and (since Linux 2.6) pipes and FIFOs.

通常,如果 O_ASYNC 标志不被具体文件支持,它会被忽略。可以检查标志是否 成功设置 后跟 F_GETFL:

// Try to set the flag
int flags;
flags= fcntl(efd, F_GETFL);
fcntl(efd, F_SETFL, flags | O_ASYNC);
// Check whether the flag is set
int new_flags = fcntl(efd, F_GETFL);
if(!(new_flags & O_ASYNC)) {
    // Failed to set the flag.
}

fcntl 到return 错误的建议,如果要设置特定文件不支持的O_ASYNC 标志。 This mailing is one of them. But according to current implementation of kernel's function setfl 他们被拒绝了:

if (((arg ^ filp->f_flags) & FASYNC) && filp->f_op->fasync)

(FASYNC 是 O_ASYNC 的同义词,->fasync 回调,如果存在,则实现具体文件标志的更改。