When an event is registered with kqueue
an ID relating to that event
type is supplied; for example a file descriptor is used to identify a file to
watch
int kq;
struct kevent ke;
kq = kqueue();
fd = open(argv[1], O_RDONLY);
EV_SET(&ke, fd, EVFILT_VNODE, EV_ADD, NOTE_DELETE | NOTE_RENAME, 0, NULL);
kevent(kq, &ke, 1, NULL, 0, NULL);
while (1) {
kevent(kq, NULL, 0, &ke, 1, NULL);
/* respond to file system event */
}
Now if I also need to respond to other event types such signals we need a new
instance of kqueue so as to avoid a conflict with the ident
argument of
kevent()
.
kq_sig = kqueue();
struct kevent ke_sig;
/* set the handler and ignore SIGINT */
signal(SIGINT, SIG_IGN);
EV_SET(&ke_sig, SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
kevent(kq_sig, &ke_sig, 1, NULL, 0, NULL);
while (1) {
kevent(kq_sig, NULL, 0, &ke_sig, 1, NULL);
/* respond signals */
}
Watching more than one event type appears to necessitate multiple threads that act on shared state (receiving a signal could close a file descriptor for example).
Is there a more general mechanism for sending a message from one thread to another using kqueue? In some cases I can conceive of enabling and disabling a filter as a means of edge-triggering another kevent.