1. epoll概念
在Linux的Man文檔中,我們可以看到如下定義
Epoll - I/O event notification facility
epoll是一種I/O事件通知機制
I/O事件
-
I/O
輸入輸出(input/output),輸入輸出的對象可以是 文件(file), 網絡(socket), 進程之間的管道(pipe), 在linux系統中,都用文件描述符(fd)來表示 -
事件
- 可讀事件, 當文件描述符關聯的內核讀緩衝區可讀,則觸發可讀事件
什麼是可讀呢? 就是內核緩衝區非空,有數據可以讀取 - 可寫事件, 當文件描述符關聯的內核寫緩衝區可寫,則觸發可寫事件
什麼是可寫呢?就是內核緩衝區不滿,有空閒空間可以寫入
- 可讀事件, 當文件描述符關聯的內核讀緩衝區可讀,則觸發可讀事件
通知機制
- 通知機制,就是當事件發生的時候,去通知他
- 通知機制的反面,就是輪詢機制
以上兩點結合起來理解
epoll是一種當文件描述符的內核緩衝區非空的時候,發出可讀信號進行通知,當寫緩衝區不滿的時候,發出可寫信號通知的機制
2. 水平觸發與邊緣觸發
水平觸發(level-trggered)
- 只要文件描述符關聯的讀內核緩衝區非空,有數據可以讀取,就一直髮出可讀信號進行通知,
- 當文件描述符關聯的內核寫緩衝區不滿,有空間可以寫入,就一直髮出可寫信號進行通知
邊緣觸發(edge-triggered)
- 當文件描述符關聯的讀內核緩衝區由空轉化爲非空的時候,則發出可讀信號進行通知,
- 當文件描述符關聯的內核寫緩衝區由滿轉化爲不滿的時候,則發出可寫信號進行通知
兩者的區別在哪裏呢?水平觸發是隻要讀緩衝區有數據,就會一直觸發可讀信號,而邊緣觸發僅僅在空變爲非空的時候通知一次,舉個例子:
- 讀緩衝區剛開始是空的
- 讀緩衝區寫入2KB數據
- 水平觸發和邊緣觸發模式此時都會發出可讀信號
- 收到信號通知後,讀取了1kb的數據,讀緩衝區還剩餘1KB數據
- 水平觸發會再次進行通知,而邊緣觸發不會再進行通知
所以邊緣觸發需要一次性的把緩衝區的數據讀完爲止,也就是一直讀,直到讀到EGAIN爲止,EGAIN說明緩衝區已經空了,因爲這一點,邊緣觸發需要設置文件句柄爲非阻塞
//水平觸發
ret = read(fd, buf, sizeof(buf));
//邊緣觸發
while(true) {
ret = read(fd, buf, sizeof(buf);
if (ret == EAGAIN) break;
}
3. epoll接口介紹
-
epoll_create
- 創建epoll實例,會創建所需要的紅黑樹,以及就緒鏈表,以及代表epoll實例的文件句柄
int epoll_create(int size);
Man文檔中說明了在老的內核版本中,入參size用來指出創建的內部數據結構的大小,目前已經可以動態調整,但是爲了兼容老的版本,所以仍然保留,這個size其實意義已經不大
- 創建epoll實例,會創建所需要的紅黑樹,以及就緒鏈表,以及代表epoll實例的文件句柄
-
epoll_ctl
-
添加,修改,或者刪除 註冊到epoll實例中的文件描述符上的監控事件
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
對於添加到epfd的文件描述符fd, 添加或者刪除或者修改, 對應的event- epfd: 通過epoll_create創建的文件描述符
- op:操作類型
EPOLL_CTL_ADD, 爲相應fd添加事件
EPOLL_CTL_MOD, 修改fd的事件
EPOLL_CTL_DEL,刪除fd上的某些事件 - fd: 操作的目標文件描述符
- event: 要操作的事件
typedef union epoll_data { void *ptr; int fd; uint32_t u32; uint64_t u64; } epoll_data_t; struct epoll_event { uint32_t events; /* Epoll events */ epoll_data_t data; /* User data variable */ }; events可以是一組bit的組合 EPOLLIN:可讀 EPOLLOUT: 可寫 EPOLLET: 邊緣觸發,默認是水平觸發
-
-
epoll_wait
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
等待註冊的事件發生,返回事件的數目,並將觸發的事件寫入events數組中- epfd: epoll實例文件描述符
- events: 數組出參,用來記錄被觸發的events,其大小應該和maxevents一致
- maxevents: 返回的events的最大個數,如果最大個數大於實際觸發的個數,則下次epoll_wait的時候仍然可以返回
- timeout: 等待事件,毫秒爲單位 -1:無限等待 0:立即返回
作者:ld9183
鏈接:https://www.jianshu.com/p/41dc33b97419
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯繫作者獲得授權並註明出處。