1

当你创建一个 kqueue 时,kqueue()你会得到一个文件描述符。但似乎无法使用select(). 我知道从 a 轮询/读取的标准kqueue()方法是 withkevent(...)但我正在尝试与一些使用select().

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

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

4

1 回答 1

3

描述 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
于 2015-09-03T20:39:21.923 回答