7

From the Kqueue Wikipedia Page:

Kqueue provides efficient input and output event pipelines between the kernel and userland. Thus, it is possible to modify event filters as well as receive pending events while using only a single system call to kevent(2) per main event loop iteration. This contrasts with older traditional polling system calls such as poll(2) and select(2) which are less efficient, especially when polling for events on a large number of file descriptors

That sounds great. I target FreeBSD for my server, and I'm handling a significant amount of network socket fd's - using a select() on them all and figuring out who to read data from. I'd rather use kevent() calls to get higher performance, since that's what it's there for!

I've read the man page for kevent on FreeBSD here but it's cryptic to me and I'm not finding good resources that explain it. An example of using kevent to replace select would solve my problem, and would also help me get a better idea of how kevent() is used.

arrowd
  • 33,231
  • 8
  • 79
  • 110
Nektarios
  • 10,173
  • 8
  • 63
  • 93

2 Answers2

12

First, create new kqueue:

int kq=kqueue();

Now register your fd in kq:

struct kevent kev;
kev.ident=your_fd;
kev.flags=EV_ADD | EV_CLEAR;
kev.filter=EVFILT_READ;
kev.fflags=0;
kev.data=0;
kev.udata=&your_data;

int res=kevent(kq,&kev,1,0,0,0);

Finally, wait for data to arrive into your socket:

struct kevent res_kevs[5];
int res=kevent(kq,0,0,res_kevs,5,0);

After return, res_kevs[i].ident will contain your socket's descriptor, res_kevs[i].data - number of bytes ready to be read.

See man kevent for more details and features.

arrowd
  • 33,231
  • 8
  • 79
  • 110
  • thank you for being the first to actually answer my question. Just to clarify - I'll have a kevent for each of my fds (thousands) and one kqueue for the whole set of them? Is that how this is normally done? – Nektarios Apr 25 '11 at 16:56
  • Yes, because each kevent() call waits only on one kqueue. Still, you can add kqueue's descriptor into another kqueue by filling kev.ident with kq. I'm not sure how it exactly works, because it's not documented for some reason. – arrowd Apr 26 '11 at 10:29
-1

What you do normally, is use libevent, which takes care of all the details for you, and also means that you can move your program on to another OS which has a different scheme (e.g. Linux and epoll) for doing something similar.

MarkR
  • 62,604
  • 14
  • 116
  • 151
  • But, I already do all the things this lib does that I care about, other than using kevent for checking whether I read from fds or not. I wouldn't want to rewrite my codebase to use this lib just for that, although if I was starting maybe I would. Also, I cringe at something hosted at "monkey.org" – Nektarios Apr 22 '11 at 19:27
  • Definitely wouldn't want a superset either! Although I can look at these pieces of software and pull the answer together I guess, but this is really not addressing the original question – Nektarios Apr 23 '11 at 01:24
  • @Nektarios: Sure it does answer it. If you use one of those libraries on a BSD system it'll use kevent and not select. – Zan Lynx Apr 25 '11 at 13:58