IO多路转接模型-----epoll
epoll:
Linux下性能最高的多路轉接模型
epoll 有3個相關的系統調用.
epoll_create
功能:創建epoll,在內核中創建eventpoll結構體,size決定了epoll最多監控多少個描述符,在Linux2.6.8之后被忽略,但是必須>0。返回一個文件描述符,作為epoll的操作句柄
struct eventpoll{ ...rb_root rbr(紅黑樹)...struct list_head rdlist(雙向鏈表)... } int epoll_create(int size)創建一個epoll的句柄.
- 自從linux2.6.8之后,size參數是被忽略的.
- 用完之后, 必須調用close()關閉
epoll_ctl
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)功能:對內核中的eventpoll 結構體進行操作:epoll采用事件結構方式對描述符進行事件監控;用戶定義struct epoll_event描述符事件結構信息;將事件信息可以拷貝到內核添加到eventpoll結構體中的紅黑數中
參數說明
- 它不同于select()是在監聽事件時告訴內核要監聽什么類型的事件, 而是在這里先注冊要監聽的事件類型.
- 第一個參數是epoll_create()的返回值(epoll的句柄).
- 第二個參數表示動作,用三個宏來表示. 、
- 第三個參數是需要監聽的fd.
- 第四個參數是告訴內核需要監聽什么事. 描述符對應的事件結構信息
第二個參數的取值:
- EPOLL_CTL_ADD :注冊新的fd到epfd中;向紅黑數中添加描述符的監控事件結構信息event
- EPOLL_CTL_MOD :修改已經注冊的fd的監聽事件;修改描述符在紅黑數中的對應事件結構信息event
- EPOLL_CTL_DEL :從epfd中刪除一個fd,從紅黑數中移除描述符的監控事件結構信息event
struct epoll_event結構如下
struct epoll_event { uint32_t events; /* 用戶對描述符進行監控的事件 */ epoll_data_t data; /* User data variable */ };typedef union epoll_data { void *ptr; int fd; uint32_t u32; uint64_t u64; } epoll_data_t;events可以是以下幾個宏的集合:
epoll_wait
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)- epfd: epoll 操作句柄
- events:epoll_event 事件結構信息數組的結點數量
- maxevents : epoll_event事件結構信息數組的結點數量
- timeout:epoll_wait 監控的等待超時時間
- 返回值:<0----監控出錯 ==0----監控超時 >0----就緒的描述符事件個數
 收集在epoll監控的事件中已經發送的事件
epoll_wait 會將就緒的描述符對應事件結構信息拷貝到events結構數組中;相當于直接告訴用戶哪個描述符就緒;用戶直接就從epoll_event 結構體數組中取出信息,對描述符直接進行相應事件操作
epoll監控流程
epoll工作原理
struct eventpoll{ ...rb_root rbr(紅黑樹)...struct list_head rdlist(雙向鏈表)... }當某一進程調用epoll_create方法時,Linux內核會創建一個eventpoll結構體,這個結構體中有兩個成 員與epoll的使用方式密切相關.
- 每一個epoll對象都有一個獨立的eventpoll結構體,用于存放通過epoll_ctl方法向epoll對象中添加進來 的事件.
- 這些事件都會掛載在紅黑樹中,如此,重復添加的事件就可以通過紅黑樹而高效的識別出來(紅黑樹的插 入時間效率是lgn,其中n為樹的高度).
- 而所有添加到epoll中的事件都會與設備(網卡)驅動程序建立回調關系,也就是說,當響應的事件發生時 會調用這個回調方法.
- 這個回調方法在內核中叫ep_poll_callback,它會將發生的事件添加到rdlist雙鏈表中.
- 在epoll中,對于每一個事件,都會建立一個epitem結構體.
 
- 當調用epoll_wait檢查是否有事件發生時,只需要檢查eventpoll對象中的rdlist雙鏈表中是否有epitem 元素即可.
- 如果rdlist不為空,則把發生的事件復制到用戶態,同時將事件數量返回給用戶. 這個操作的時間復雜度 是O(1).
epoll事件觸發方式:
水平觸發–EPOLLT/邊緣觸發EPOLLET
水平觸發方式
可讀事件就緒:接受緩沖區數據大小,大于低水位標記(默認1字節)
 可寫事件就緒:發送緩沖區中空閑大小,大于低水位標記(默認1字節)
 只要接受/發送緩沖區中數據/剩余空間大小大于低水平標記就會一直觸發事件
邊緣觸發方式
可讀事件就緒:接受緩沖區中,只有新數據到來的時候才會觸發一次
 可寫事件就緒:發送緩沖區中,只有從剩余空間大小從0變為大于0的時候才會觸發
注意事項
邊緣觸發方式中,只有新數據到來的時候,可讀事件才會觸發一次
 需要用戶在這一次事件觸發中將緩沖區中的數據全部讀取完畢(循環讀,直到不能讀為止)
 但是套接字默認recv沒有數據的時候會阻塞;為了避免循環讀取數據導致程序流程因為阻塞而無法繼續推進,因此需要將描述符設置為非阻塞
fcntl
int fcntl(int fd,int cmd, .../*arg*/);fd : 要設置的描述符cmd : 對描述符要進行的操作F_SETFL 通過arg參數設置描述符屬性狀態F_GETFL 返回描述符的屬性狀態信息 ,arg被忽略arg:要設置的描述符屬性狀態信息O_NONBLOCK 將描述符設置為非阻塞epoll優缺點分析
缺點
IO多路轉接模型的適用場景
對大量描述符進行監控,但是同一時間只有少量描述符活躍的場景
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的IO多路转接模型-----epoll的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 输卵管堵塞还能自然通开吗
- 下一篇: 时间轴样式怎么将两个时间点连接起来
