理解這三個輪詢函式差異的關鍵在於理解其輪詢的檔案描述符(socket也是檔案)的資料結構。
函式定義:
int
select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exeptfds, struct timeval *timeout);
// fd_set操作巨集
void fd_set(int fd, fd_set *fdset);
void fd_clr(int fd, fd_set *fdset);
void fd_isset(int fd, fd_set *fdset);
void fd_zero(fd_set *fdset);
監聽的事件型別有限,只有3種;readfds、writefds和exeptfds有兩重角色,第一層是當做要監聽的檔案描述符集合來傳給核心監聽;第二層是當做發生事件的檔案描述符結果集合。因此每次輪詢處理完事件,需要重新設定需要監聽的檔案描述符;
事件和檔案描述符沒有繫結,因此要處理事件需要輪詢所有的已accept到的檔案描述符。
函式定義:
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd
說明:與select相比這種函式設計清晰簡潔,將檔案描述符和事件通過pollfd結構體來進行了繫結,並且區分了註冊的時間和實際發生的事件。但是其和select一樣,最終輪詢的結果都是所有已經註冊的檔案描述符的集合。
函式定義:
/* 建立核心事件表,返回的就是事件表的檔案描述符 */
int epoll_create(int size);
/* 往核心事件表註冊、修改、刪除指定fd上的事件 */
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);
我們這裡講的統一事件源中的事件源是指io事件和訊號。訊號原理可以參見《linux學習系列-訊號》。通常我們通過輪詢函式來處理io事件,既然要統一,那麼自然也要使用輪詢函式來處理訊號。典型的處理方案是:訊號發生時,訊號處理函式一般通過管道來通知程式主迴圈訊號值,那麼主迴圈中的輪詢函式就可以通過輪詢函式來監聽管道上的io事件即可。這樣就實現了io事件和訊號的統一處理。
輪詢函式封裝
如果你需要持續檢查資料更新,但系統中沒有 websocket,則可以使用這個工具來執行操作。它非常適合上傳檔案時,想要持續檢查檔案是否已完成處理的情況,或者使用第三方 api 例如 dropbox 或 uber 並且想要持續檢查過程是否完成或騎手是否到達目的地的情況。async function p...
Linux裝置輪詢機制分析
所謂的裝置輪詢機制實際上就是利用網絡卡驅動程式提供的napi機制加快網絡卡處理資料報的速度,因為在大流量的網路環境當中,標準的網絡卡中斷加上逐層的資料拷貝和系統呼叫會占用大量的cpu資源,而真正用於處理這些資料的資源卻很少。乙個基本的想法是對於大流量網路,如果發現乙個dma傳輸中斷 這表明乙個網路資...
Linux學習系列 訊號
訊號是軟體中斷,提供了典型的非同步機制。每個訊號有乙個編號,訊號分為兩類 非實時訊號和實時訊號。0 31編號屬於非實時訊號 31 63編號屬於實時訊號。為什麼會分為這兩類訊號呢?這個主要是因為歷史原因,首先實現的是非實時訊號,非實時訊號也成為不可靠訊號,是因為其實現機制導致這類訊號可能會丟失 而實時...