是否可以使用 select() 轮询 kqueue 的文件描述符?

ipm*_*mcc 3 macos select freebsd kqueue

当你创建一个 kqueue 时,kqueue()你会得到一个文件描述符。但看来这个文件描述符不能用 进行有意义的轮询select()。我知道轮询/读取 a 的标准kqueue()方法是 withkevent(...)但我正在尝试与一些使用select().

这里的目标是能够触发可以通过select基于此的轮询机制检测到的“用户事件”(即使该事件最终需要kevent()稍后使用“消耗”)。EVFILT_USER这看起来像是天生要做的事情,但快速实验表明select(),当在 kqueue 中添加(并触发)事件时,不会将 kqueue 的 fd 报告为已准备好读取,它只是超时(或阻塞)永远)。(但是等效的kevent()调用确实看到/返回该事件。)

难道我做错了什么?或者是不可能用 轮询 kqueue 的 fd select()

arr*_*owd 5

描述 kqueue/kevent 的论文说道(第 6.5 节):

由于普通文件描述符引用 kqueue,因此它可以参与通常可以在描述符上执行的任何操作。应用程序可以 select()、poll()、close(),甚至创建一个引用 kqueue 的 kevent;

FreeBSD 确实是这样,我已经用以下代码检查了这一点:

  struct kevent e;
  fd_set fdset;
  int kq=kqueue();

  EV_SET(&e, 1, EVFILT_USER, EV_ADD, 0, 0, NULL);
  kevent(kq, &e, 1, 0, 0, 0); // register USER event filter

  EV_SET(&e, 1, EVFILT_USER, EV_ADD, NOTE_TRIGGER, 0, NULL);
  kevent(kq, &e, 1, 0, 0, 0); // trigger USER event

  FD_ZERO(&fdset);
  FD_SET(kq,&fdset);

  select(FD_SETSIZE,&fdset, 0, 0, 0); // wait for activity on kq

  int res = kevent(kq, 0, 0, &e, 1, 0); // get the event
Run Code Online (Sandbox Code Playgroud)