kqueue.1 - wyc902/redis GitHub Wiki

kqueue 其实是epoll在freebsd和macos上的变种。原理和epoll类似,实现不一样。 网上对kqueue对实现介绍对比较少。可参考文章http://people.freebsd.org/~jlemon/papers/kqueue.pdf 比较关键对结构是knote(对应应用层对kevent)和kqueue。

int kqueue(void) 
这个函数会生成一个内核kqueue事件队列,返回文件描述符类似epoll的epfd,通过其操作事件队列

 struct kevent { 
     uintptr_t ident;      /* 事件 ID 一般是fd */ 
     short     filter;       /* 事件过滤器 */ 
     u_short   flags;      /* 行为标识 */ 
     u_int     fflags;       /* 过滤器标识值,一般和data结合使用*/ 
     intptr_t  data;      /* 过滤器数据 */ 
     void      *udata;       /* 应用透传数据,用的不多感觉 */ 
 };

filter 其实就是kevent监听的事件,例如读EVFILT_READ,写EVFILT_WRITE等。这样一来,一组ident,filter唯一确定了一个kevent。 flags 用的较多的是:EV_ADD指示加入事件到 kqueue。EV_DELETE指示将传入的事件移除kqueue。请看函数:

int kevent(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout);

kq: kqueue 的文件描述符
changelist: 注册/移除的事件数组; 
nchanges: changelist 的元素个数。 
eventlist: 满足条件的通知事件数组; nevents: eventlist 的元素个数。
timeout: 等待事件到来时的超时时间,0,立刻返回;NULL,一直等待;有一个具体值,等待 timespec 时间值。 

返回值:可用事件的个数

如果将eventlist设为0,就是不传eventlist,这个函数会根据changelist注册相应事件到kqueue。如果事件关联的fd被close,则kevent会自动被移除出kqueue。如果changelist中的kevent已在kqueue,可以通过函数来修改kevent的元素,例如flag。

如果不传changelist,传入其他合法参数,eventlist中就是ready的事件集合。