I/O復用 select/poll/epoll

轉載自I/O復用 select/poll/epoll

一、概述

I/O復用使得程序能同時監(jiān)聽多個文件描述符,這對提高程序的性能至關重要。

I/O復用雖然能同時監(jiān)聽多個文件描述符,但本身是阻塞的。并且當多個描述符同時就緒時,如果不采用額外的措施,程序就只能按照順序依次處理其中的每個文件描述符,使得服務器程序看起來像串行工作一樣。要實現并發(fā),只能使用多進程或者多線程等方式實現。

linux下實現I/O復用的系統(tǒng)調用主要有select、poll、epoll。

二、select

select系統(tǒng)調用的用途是,在一段時間內,監(jiān)聽用戶感興趣的文件描述符上可寫和異常事件。

#include <sys/select.h>
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
            const struct timeval *timeout);

1、nfds

nfds參數指被監(jiān)聽文件描述符的總數,通常設為做大文件描述符值加1。

2、readfds, writefds, exceptfds

分別指向可讀,可寫和異常事件對應的文件描述符集合。select通過這三個參數傳入自己感興趣的文件描述符,內核修改它們來通知應用程序哪些文件描述符已經就緒。

fd_set結構體僅包含一個整型數組,該數組每一個元素的每一位都標記一個文件描述符,是一個bitmap。其最大文件描述符的數量由FD_SETSIZE指定,這限制了select能同時處理的文件描述符總量。

3、timeout

超時時間。該參數與poll、epoll不同,是一個timeval結構類型指針??梢跃_到微妙。如果給timeval中tv_sec和tv_usec傳遞的都是0,則表示立即返回,非阻塞。如果給timeout傳遞null,則select將一直阻塞,直到某個文件描述符就緒。

4、返回值

成功時,返回就緒(可讀、可寫和異常)文件描述符總數。超時時間內沒有任何文件返回0。失敗返回-1,并設置errno。如果等待期間,接收到信號,則立刻返回-1,并設置errno為EINTR。

三、poll

poll和select相似,也是在指定時間內輪詢一定數量的文件描述符,以測試其中是否有就緒者。poll原型如下:

#include<poll.h>
int poll(struct pollfd * nfds_t nfds, int timeout);

struct pollfd{
  int fd;
  short events;
  short revents;
};

1、fds

fds參數是一個pollfd結構類型的數組,它指定了所有我們感興趣文件描述符上發(fā)生的可讀、可寫和異常等事件。

pollfd中fd是文件描述符,events是注冊的事件,revents是實際發(fā)生的事件,由內核填充,用來通知應用程序fd上實際發(fā)生了哪些事件。

2、nfds

指定被監(jiān)聽事件幾何fds的大小
typedef unsigned long int nfds_t;

3、timeout

poll的超時時間。單位是毫秒,當值為-1時,poll調用將永遠阻塞,直到某個事件發(fā)生;當timeout為0,poll將立即返回。

4、返回值

返回值與select相同

四、epoll

epoll是linux特有的I/O復用函數。它在實現和使用上與select、poll有很大差別。

  • 用一組函數來完成任務,而不是單個函數。
  • 把用戶關系的文件描述符上的事件放在內核里的一個事件表中,無需像select、poll那樣每次調用都重復傳入文件描述符和事件集。
  • 需要一個額外的文件描述符,來唯一標識內核中這個事件表。這個文件描述符由epoll_create函數創(chuàng)建。
1、epoll_create
#include<sys/epoll.h>
int epoll_create(int size);

size參數現在不起作用,只是給內核一個提示,告訴它事件表需要多大。該函數返回的文件描述符用于其它epoll函數的第一個參數,以指定要訪問的內核事件表。

2、epoll_ctl
#include<sys/epoll.h>
int epoll_ctl(int epfd, int op, int fd, struct epoll_event * event);

/*op有三種類型:
EPOLL_CTL_ADD,往事件表中注冊fd上的事件
EPOLL_CTL_MOD,修改fd上的注冊事件
EPOLL_CTL_DEL,刪除fd上的注冊事件*/

struct epoll_event {
  __uint32_t events;  /* Epoll events */
  epoll_data_t data;  /* User data variable */
};

3、epoll_wait

是epoll系統(tǒng)調用主要的接口函數。它在一段時間內等待一組文件描述符上的事件,其原型如下:

#include<sys/epoll.h>
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

  • timeout含義與poll相同
  • 函數返回的含義與select/poll相同
  • maxevents表示最多監(jiān)聽多少個事件

epoll_wait如果檢測到事件,就將所有就緒事件從內核事件表中復制到它的第二個參數events指向的數組中。這個數組只用于輸出epoll_wait檢測到的事件。而不像select/poll那樣即用于輸入,也用于輸出。因此提高了應用程序索引就緒文件的描述符的效率。

4、LT和ET模式

epoll對文件描述符的操作有兩種模式:LT(level trigger,電平觸發(fā))和ET(edge trigger)

LT模式是默認的工作模式,此模式下epoll相當于一個效率較高的poll。當往epoll內核事件表中注冊一個文件描述符上的EPOLLET事件時,epoll將采用ET模式,ET是epoll高效的規(guī)則模式。

對于LT,epoll_wait檢測到其上有事件發(fā)生并將此事件通知應用程序后,應用程序可以不立即處理該事件。因此應用程序下次調用epoll_wait時,還將向應用程序通知該事件,直至該事件被處理。

對于ET,epoll_wait檢測到其上有事件發(fā)生并將此事通知應用程序后,應用程序必須立即處理該事件,后續(xù)epoll_wait將不再向應用程序通知這一事件。ET模式在很大程度上降低了同一事件被重復觸發(fā)次數,因此效率比LT高。每個使用ET模式的文件描述符都應該是非阻塞的。如果文件描述符是阻塞的,那么讀寫操作都會因沒有后續(xù)事件而處于阻塞狀態(tài)。

五、三組I/O復用函數比較

  • 三者都由timeout參數指定超時時間,直到一個或多個文件描述符上有時間發(fā)生時返回,返回值就是文件描述符的數量。返回0表示沒有事件發(fā)生。

  • 1、select沒有文件描述符與事件綁定,它僅僅是一個文件描述符的幾何,因此select需要提供三個此類參數來區(qū)分傳入的可讀,可寫,異常事件。一方面使得其不能處理更多事件,另一方面內核對fd_set集合在線修改,應用程序下次需要重置此三個fd_set集合。

  • 2、poll則比select聰明些,它把文件描述符和事件都定義在其中,任何任何事件都被統(tǒng)一處理,從而簡化了編程接口。由于select/poll每次都需要返回整個用戶注冊事件集合,應用程序索引文件描述符時間復雜度為O(n)

  • 3、epoll在內核維護一個事件表,并提供epoll_ctl來控制向其中添加、刪除、修改事件。這樣,epoll調用直接從該內核事件表中取得用戶注冊事件,從而無需反復從用戶空間讀入這些事件。epoll_wait系統(tǒng)調用的events參數僅用來返回就緒事件,使得應用程序索引就緒事件描述符的時間復雜度為O(1)

  • 4、poll/epoll分別采用nfds和maxevents參數指定最多監(jiān)聽的文件描述符合事件。這兩個數值都能達到系統(tǒng)允許的最大最大文件描述符數,65536。而select允許最大監(jiān)聽最大文件描述符數量通常有限制。

  • 5、select/poll都支持相對低效的LT模式,epoll可在ET模式下工作,epoll還支持EPOLLONESHOT事件

  • 6、活動連接比較多是,epoll效率未必比select、poll高,因為此時回調函數被觸發(fā)過于頻繁。epoll適用于連接數量較多,但活動連接相對較少的情況。

  • 7、select,poll,epoll本質上都是同步I/O,因為他們都需要在讀寫事件就緒后自己負責進行讀寫,也就是說這個讀寫過程是阻塞的,而異步I/O則無需自己負責進行讀寫,異步I/O的實現會負責把數據從內核拷貝到用戶空間。

參考文獻:
1、Linux IO模式及 select、poll、epoll詳解
2、Anker—工作學習筆記
3、細說select、poll和epoll之間的區(qū)別與優(yōu)缺點
4、select,poll,epoll優(yōu)缺點及比較

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容