kqueue用法简介
什么是kqueue和IO复用
kqueue是在UNIX上比较高效IO复用技术。
所谓的IO复用,就是同时等待多个文件描述符就绪,以系统调用的形式提供。如果所有文件描述符都没有就绪的话,该系统调用阻塞,否则调用返回,允许用户进行后续的操作。
常见的IO复用技术有select, poll, epoll以及kqueue等等。其中epoll为Linux独占,而kqueue则在许多UNIX系统上存在。
相关的数据结构
kqueue有三个主要的东西:struct kevent结构体,EV_SET宏以及kevent函数。
struct kevent结构体是用于调度的事件
// struct kevent结构体
struct kevent {
// 该事件关联的文件描述符,如socket中的fd句柄
uintptr_t ident;
/*
* 可以指定监听类型
* 如EVFILT_READ=读,EVFILT_WRITE=写,EVFILT_TIMER=定时器事件,EVFILT_SIGNAL=信号,EVFILT_USER=用户自定义事件
*/
int16_t filter;
/**
* 操作方式
* EV_ADD 添加,EV_DELETE 删除,EV_ENABLE 激活,EV_DISABLE 不激活
*/
uint16_t flags;
uint32_t fflags; /* 第二种操作方式,NOTE_TRIGGER 立即激活等等 */
intptr_t data; /* int 型的用户数据,socket 里面它是可读写的数据长度 */
void *udata; /* 指针类型的数据,你可以携带任何想携带的附加数据。比如对象 */
};
EV_SET 是用于初始化kevent结构的便利宏
EV_SET(&kev, ident, filter, flags, fflags, data, udata);
kevent函数
int kevent(int kq, // kqueue的句柄
const struct kevent *changelist, // 是 kevent 的数组,就是一次可以添加多个事件
int nchanges, // 是 changelist 数组长度
struct kevent *eventlist, // 是待接收事件的数组,里面是空的,准备给 kqueue 放数据的
int nevents, // 是 eventlist 数组长度,传了 eventlist参数后,kevent() 将会阻塞等待事件发生才返回,返回的全部事件在 eventlist 数组里面。
const struct timespec *timeout); // 是阻塞超时时间,超过这个时间就不阻塞了,直接返回
使用kqueue
#include <sys/event.h>
#include <sys/types.h>
// 引入头文件
int kq = kqueue();
// 获取kqueue句柄
struct kevent evt; // 创建
EV_SET(&evt, sock, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, NULL); // 赋值
kevent(kq, &evt, 1, NULL, 0, NULL); // 添加
// 创建并添加监听事件
struct kevent events[Max_Event_Count];
int ret = kevent(kq, NULL, 0, events, Max_Event_Count, NULL);
// 监听事件的发生
// kevent() 是阻塞调用,等到有事件才返回。阻塞时进程处于sleep状态,有事件时系统激活kqueue,kevent()返回
// events 是 kqueue 返回的事件数组
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。