【多路複用】epoll原理

epoll的系統調用很簡單,只有三個,其定義如下:

int epoll_create(int size);   

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

一,epoll的實現原理就是基於這三個函數來實現的,具體步驟如下:

首先,需要調用epoll_create來創建一個epoll的文件描述符,內核會同時創建一個eventpoll的數據結構。這個數據結構裏面會包含兩個東西,一個是紅黑樹,專門用於存儲epoll_ctl註冊進來的fd文件描述符;另外一個是就緒鏈表,用來存儲epoll_wait調用相關的,已經就緒的那些fd文件描述符。

struct eventpoll{

struct rb_root rbr; // 紅黑樹的根節點,存儲着所有添加到epoll中的需要監控的事件

struct list_head rdlist;//  雙鏈表中存放着將要通過epoll_wait返回給用戶的滿足條件的事件

 };


其次,因爲epoll中的所有事件,都與網卡驅動程序建立回調關係,當相應的事件發生的時候,會通過這個回調函數,將發生的事件添加到就緒鏈表當中。

最後,當調用epoll_wait檢查是否有事件發生時,只需要檢查eventpoll對象中的rdlist雙鏈表中是否有需要處理的事件。如果rdlist不爲空,則把發生的事件複製到用戶態,同時將事件數量返回給用戶。

二,系統函數介紹:

1、epoll_create

調用epoll_create方法創建一個epoll的句柄,該句柄會佔用一個fd,用完之後需要回收。

2、epoll_ctl

epoll的事件註冊函數,通過epoll_ctl註冊要監聽的事件類型。

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

epfd:epoll_create創建的epollfd。

events:表示動作類型。三中類型,如下所示:

1) EPOLL_CTL_ADD:註冊新的fd到epfd中;

2) EPOLL_CTL_MOD:修改已經註冊的fd的監聽事件;

3) EPOLL_CTL_DEL:從epfd中刪除一個fd。

fd:需要監聽的fd。

event:告訴內核需要監聽的事件。(EPOLLIN:表示對應的文件描述符可讀(包括對端Socket); EPOLLOUT:表示對應的文件描述符可寫; EPOLLPRI:表示對應的文件描述符有緊急數據可讀(帶外數據); EPOLLERR:表示對應的文件描述符發生錯誤; EPOLLHUP:表示對應的文件描述符被掛斷; EPOLLET:將EPOLL設爲邊緣觸發(Edge Triggered),這是相對於水平觸發(Level Triggered)而言的。 EPOLLONESHOT:只監聽一次事件,當監聽完這次事件之後,如果還需要繼續監聽這個socket,需要再次調用epoll_ctl

3、epoll_wait

int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

功能:收集在epoll監控的事件中已經發生的事件。

參數:

events:是分配好的epoll_event結構體數組,epoll將會把發生的事件賦值到events數組中(events不可以是空指針,內核只負責把數據賦值到這個event數組中,不會去幫助我們在用戶態分配內存)。

maxevents:告訴內核這個events數組有多大,這個maxevents的值不能大於創建epoll_create時的size。

timeout:是超時時間(毫秒)。

返回值:如果函數調用成功,則返回對應IO上已準備好的文件描述符數目,如果返回0則表示已經超時。


備註: 參考博客:

https://blog.csdn.net/zhaobryant/article/details/80557262

https://blog.csdn.net/shenya1314/article/details/73691088


灰子做於二零一九年二月十六日。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章