能否使用 `select()` 轮询 kqueue 的文件描述符?

3
当您使用kqueue()创建kqueue时,会返回一个文件描述符。但是似乎这个文件描述符不能被select()有意义地轮询。我知道用kevent(...)轮询/读取的标准方式,但我正在尝试集成一些使用select()轮询文件描述符的旧代码。
本次目标是能够触发“用户事件”,以便此基于select的轮询机制可以检测到它(即使最终需要使用kevent()“消耗”事件)。这似乎是EVFILT_USER应该实现的功能,但是快速实验表明,当在kqueue中添加(并触发)事件时,select()不会报告kqueue的fd已经准备好读取,它只是超时(或永远阻塞)。 (但等效的kevent()调用确实看到/返回了事件。)
我做错了什么吗?还是使用select()无法轮询kqueue的fd?
1个回答

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接