如何用kevent()替换select()以获得更高的性能?

时间:2011-04-22 14:22:46

标签: c macos performance freebsd kqueue

来自Kqueue Wikipedia Page

Kqueue在内核和用户空间之间提供高效的输入和输出事件管道。因此,可以修改事件过滤器以及接收未决事件,同时每个主事件循环迭代仅使用对kevent(2)的单个系统调用。这与较旧的传统轮询系统调用(如poll(2)和select(2))形成对比,后者效率较低,尤其是在对大量文件描述符上的事件进行轮询时

听起来不错。我为我的服务器定位FreeBSD,我正在处理大量的网络套接字fd - 在它们上面使用select()并确定从哪里读取数据。我宁愿使用kevent()调用来获得更高的性能,因为它就是它的用途!

我读过man page for kevent on FreeBSD here,但这对我来说很神秘,我找不到解释它的好资源。使用kevent替换select的一个例子可以解决我的问题,也可以帮助我更好地了解如何使用kevent()。

2 个答案:

答案 0 :(得分:11)

首先,创建新的kqueue:

int kq=kqueue();

现在在kq中注册你的fd:

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);

最后,等待数据进入你的套接字:

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

返回后,res_kevs[i].ident将包含套接字的描述符res_kevs[i].data - 准备好读取的字节数。

有关详细信息和功能,请参阅man kevent。

答案 1 :(得分:-1)

您通常使用libevent,来处理所有细节,也意味着您可以将程序移动到另一个具有不同方案的操作系统(例如Linux和epoll)做类似的事情。