1. 程式人生 > 實用技巧 >kqueue用法簡介

kqueue用法簡介

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 返回的事件陣列

參考:https://www.freebsd.org/cgi/man.cgi?kqueue