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

如何用kevent()替换select(),以获得更高的性能?,c,macos,performance,freebsd,kqueue,C,Macos,Performance,Freebsd,Kqueue,从: Kqueue在内核和用户之间提供了高效的输入和输出事件管道。因此,在每次主事件循环迭代中仅使用对kevent(2)的单个系统调用时,可以修改事件过滤器以及接收挂起事件。这与较旧的传统轮询系统调用(如poll(2)和select(2))形成对比,后者效率较低,尤其是在对大量文件描述符上的事件进行轮询时 听起来不错。我将FreeBSD作为我服务器的目标,并且我正在处理大量的网络套接字fd——在它们上使用select()并确定从谁那里读取数据。我宁愿使用kevent()调用来获得更高的性能,因为

从:

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

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


我读过这本书,但它对我来说很神秘,我没有找到好的资源来解释它。使用kevent替换select的一个例子可以解决我的问题,也可以帮助我更好地了解kevent()的使用方式。

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

首先,创建新队列:

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。

但是,除了使用kevent检查是否从fds读取之外,我已经完成了该库所做的所有我关心的事情。我不想重写我的代码库来使用这个库,尽管如果我开始的话,我可能会这样做。而且,我对“monkey.org”上的东西感到畏缩,我肯定也不想要超集!虽然我可以看看这些软件片段,并把答案拉在一起,我想,但这真的不是解决原来的问题question@Nektarios:当然可以。如果您在BSD系统上使用其中一个库,它将使用kevent而不是select。感谢您第一个真正回答我的问题。只是想澄清一下——我会为我的每一个FD(数千)设置一个kevent,为整套FD设置一个kqueue?通常是这样做的吗?是的,因为每个kevent()调用只在一个队列上等待。仍然可以通过用kq填充kev.ident将kqueue的描述符添加到另一个kqueue中。我不确定它到底是如何工作的,因为出于某种原因它没有被记录下来。