Linux下開發-IO複用

啊浪的部落格發表於2017-11-05

select、pselect

int select(int n, fd_set *readfds,fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

int pselect(int n, fd_set *readfds,fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, constsigset_t *sigmask);


select和pselect都是等待一系列的檔案描述符(int)的狀態發生變化。

這兩個函式基本上是一致,但是有三個區別:

1、select函式用的timeout引數是timeval的結構體(包含秒和微秒),而pselect用的是timespec結構體(包含秒和納秒),更精確。

2、select函式可能會為了指示還剩多長時間而更新timeout引數,然而pselect不會改變timeout引數。

3、select函式沒有sigmask引數,當pselect的sigmask引數為null時,兩者行為時一致的。有sigmask的時候,pselect相當於如下的select()函式,在進入select()函式之前手動將訊號的掩碼改變,並儲存之前的掩碼值;select()函式執行之後,再恢復為之前的訊號掩碼值。

 

缺點:

1、同時監聽的fd數量有限(1024)

2、函式返回後,需要全量遍歷所有的fd,詢問是否有事件發生,在fd較多的時候效能較差。




poll

跟select差不多,只是API優化了。且沒有fd監聽數量的限制。

缺點:

1、函式返回後,需要全量遍歷所有的fd,詢問是否有事件發生,在fd較多的時候效能較差




epoll

在poll的基礎上優化,函式直接返還發生事件的fd。

 

LTET

LT(level triggered 水平觸發)是預設的工作方式,並且同時支援block和no-blocksocket。在這種做法中,核心告訴你一個檔案描述符是否就緒了,然後你可以對這個就緒的fd進行IO操作。如果你不作任何操作,核心還是會繼續通知你的,所以,這種模式程式設計出錯誤可能性要小一點。傳統的select/poll都是這種模型的代表。

 

ET (edge-triggered 邊緣觸發)是高速工作方式,只支援no-block socket。在這種模式下,當描述符從未就緒變為就緒時,核心通過epoll告訴你。然後它會假設你知道檔案描述符已經就緒,並且不會再為那個檔案描述符傳送更多的就緒通知


EPOLLOUT事件

一、EPOLLOUT事件在連線時觸發一次,表示可寫。

二、其他時候想要觸發,那你要先準備好下面條件:

1.某次write,寫滿了傳送緩衝區,返回錯誤碼為EAGAIN。

2.對端讀取了一些資料,又重新可寫了,此時會觸發EPOLLOUT。

 

如果你真的想強制觸發一次,也是有辦法的,直接呼叫epoll_ctl重新設定一下event就可以了,event跟原來的設定一模一樣都行(但必須包含EPOLLOUT),關鍵是重新設定,就會馬上觸發一次EPOLLOUT事件。

 

 

 

 

 

相關文章