I/O復用講解

I/O復用:即使得程序可以同時監聽多個文件描述符。

1、select系統調用

(1)系統調用原型:

圖1

(2)參數介紹:其中nfds指定被監聽的文件描述符的總數,通常被設置為select監聽的所有文件描述符中的最大值加1;readfds、writefds、exceptfds分別指向可讀、可寫和異常等對應的文件描述符集合,select調用返回時,內核將修改它們來通知應用程序哪些文件描述符已經就緒,它們都是fd_set結構指針類型,fd_set結構體定義如下:

圖2

由以上定義可知,fd_set結構體僅包含一個整形數組,該數組的每個元素的每一位標記一個文件描述符。_FD_SETSIZE限制了select能同時處理的文件描述符的總量。由于位操作過于繁瑣,采用下面的函數來訪問fd_set結構體中的位:

圖3

timeout用來設置select函數的超時時間,它是一個timeval結構類型的指針,該結構體定義如下:

圖4

若給timeout的兩個參數都傳0,則select立即返回;若給timeout傳遞NULL,則select一直阻塞,直到某個文件描述符就緒。

(3)系統調用介紹:select成功時返回就緒(可讀、可寫和異常)文件描述符的總數。

2、poll系統調用

(1)系統調用原型:

圖5

(2)參數介紹:fds是一個pollfd結構類型的數組,它指定所有我們感興趣的文件描述符上發生的可讀、可寫和異常的事件,pollfd結構體定義如下:

圖6

nfds指定被監聽事件集合fds的大小,其定義如下:

圖7

timeout指定poll的超時值,單位是ms;當timeout為-1時,poll調用將永遠阻塞,直到某個事件發生,當timeout值為0時,poll調用立即返回。

3、epoll系統調用

聲明:epoll與select、poll不同,它將用戶關心的文件描述符放在內核里的一個事件表中,不像select、poll,每次調用都要重復傳入文件描述符集或事件集。

(1)系統調用相關函數介紹:

一、epoll需要使用一個額外的文件描述符來唯一標識內核中的這個事件表,通過以下函數創建:

圖8

其中size只是告訴內核事件表需要多大的提示。

二、操作內核事件表的函數:

圖9

epfd是上述函數創建得到的文件描述符,通過它來訪問內核事件表,op指定操作的類型,有如下3種:

圖10

event指定事件,它是epoll_event結構指針類型,有關定義如下:

圖11

其中events事件常用的有EPOLLIN(讀事件)和EPOLLOUT(寫事件)。epoll_data_t是一個聯合體,它的4個成員中使用最多的是fd,它指定事件所從屬的目標文件描述符。

函數成功返回0,失敗返回-1。

三、在一段時間內等待一組文件描述符上的事件的函數:

圖12

函數成功返回就緒的文件描述符的個數,失敗返回-1。

maxevents指定最多監聽多少個事件,必須大于0,該函數若檢測到事件,就將所有就緒事件從內核事件表中復制到它的第二個參數events指向的數組中。

四、epoll的LT(水平觸發)和ET(邊沿觸發)模式。

LT:系統默認的工作模式,即阻塞,也就是會再次通知應用程序響應事件;

ET:通過注冊EPOLLET事件設置,它不會再次通知。

五、epoll的EPOLLONESHOT事件

一個socket上的某個事件很可能被觸發多次,在并發程序中,一個線程或者進程在讀取完某個socket上的數據后開始處理這些數據,而在數據處理過程中該socket上又有新數據可讀(即EPOLLIN再次觸發),這是就會喚醒另外一個線程或者進程來讀取這些數據,這種局面就是兩個線程(進程)同時操作一個socket,為了避免這種情況,注冊EPOLLONESHOT事件可以使一個socket連接在任一時刻僅被一個線程(進程)處理。

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

圖13

epoll適用于連接數量多,但活動連接少(因為若活動連接數多,會頻繁調用回調函數)。

5、基于Reactor模式的I/O框架庫包括以下組件:

(1)句柄-----------即I/O框架庫要處理的對象(I/O事件、信號、定時事件,三者合稱為統一事件源)。一個事件源通常和一個句柄綁定在一起。當內核檢測到就緒事件時,它將通過句柄來通知應用程序這一事件。在LINUX環境下,I/O事件對應的句柄是文件描述符,信號事件對應的句柄是信號值。

(2)事件多路分發器-----------因為程序需要循環地等待并處理隨機或異步到來的事件,而等待事件一般使用I/O復用技術實現。將系統支持的各種I/O復用系統調用封裝成統一接口,稱為事件多路分發器(方法是等待事件的核心函數,內部調用的是select、poll、epoll_wait),此外,它還要提供register_event(向事件多路分發器中添加事件,被register_handler調用)和remove_event(刪除事件多路分發器中的事件,被remove_handler調用)的方法。

(3)事件處理器和具體事件處理器-----------事件處理器執行事件對應的業務邏輯。它通常包含一個或多個handle_event回調函數(等待事件-->依次處理所有就緒事件對應的事件處理器),這些回調函數在事件循環中被執行。I/O框架庫提供的事件處理器通常就是個接口(通常斜寫為虛函數),用戶需要繼承它來實現自己的事件處理器,即具體事件處理器。此外,它還提供一個get_handle方法,返回與該事件處理器關聯的句柄(解釋:當事件多路分發器檢測到有事件發生時,它是通過句柄來通知應用程序的,而只有事件處理器和句柄綁定,才能在事件發生時獲取到正確的事件處理器)。

2、使用Libevent的案例:高性能的分布式內存對象緩存軟件memcached

3、高性能I/O框架庫Libevent的優點:(1)跨平臺支持(2)統一事件源(3)線程安全

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • I/O復用基本概念 I/O多路復用技術通過把多個I/O的阻塞復用到同一個select的阻塞上,從而使得系統在單線程...
    Ycres閱讀 994評論 0 0
  • epoll概述 epoll是linux中IO多路復用的一種機制,I/O多路復用就是通過一種機制,一個進程可以監視多...
    發仔很忙閱讀 10,962評論 4 35
  • 一、概述 I/O復用使得程序能同時監聽多個文件描述符,這對提高程序的性能至關重要。 I/O復用雖然能同時監聽多個文...
    saviochen閱讀 1,088評論 0 4
  • 本文摘抄自linux基礎編程 IO概念 Linux的內核將所有外部設備都可以看做一個文件來操作。那么我們對與外部設...
    lintong閱讀 1,631評論 0 4
  • 同步、異步、阻塞、非阻塞 同步 & 異步 同步與異步是針對多個事件(線程/進程)來說的。 如果事件A需要等待事件B...
    rainybowe閱讀 2,919評論 0 9