Linux :IO多路復用模型

轉載:http://blog.csdn.net/mr253727942/article/details/50827127

一、IO多路復用定義

IO多路復用允許應用在多個文件描述符上阻塞,并在某一個可以讀寫時通知, 一般遵循下面的設計原則:、

  1. IO多路復用:任何文件描述符準備好IO時進行通知
  2. 在文件描述符就緒前進行睡眠。
  3. 喚醒:哪個準備好了
  4. 在不阻塞的情況下處理所有IO就緒的文件描述符
  5. 返回第一步

Linux下提供了三種IO多路復用方案,select、poll和epoll。

二、select IO 多路復用

看一下select 函數的定義:

int select (int n,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);FD_CLR(int fd, fd_set *set);FD_ISSET(int fd, fd_set *set);FD_SET(int fd, fd_set *set);FD_ZERO(fd_set *set);

上面的定義中可以看到select主要檢測三類文件描述符,分別等待不同的事件。

  • readfds

    確認是否有可讀數據
    
  • writefds

    確認是否有可寫數據
    
  • exceptefds

    確認是否有異常發生或者出現帶外數據。
    

第一個參數n,等于所有集合中文件描述符的最大值加一。select()的調用者需要找到最大的文件描述符值加一作為第一個參數。

成功返回時,返回哪一個文件描述符,就說明該文件描述符準備好無阻塞IO。對于timeout,select操作可以設置一個超時時間,超時后即使沒有文件描述符IO就緒也會返回。

select的缺點:

1.每次調用select,都需要把fd集合從用戶態拷貝到內核態?
2。同時需要遍歷所有fd?
3。支持的文件描述符默認只有1024

三、poll IO 多路復用

poll()系統調用也是一個IO多路復用解決方案,解決了 一些select的不足,下面給出poll的定義:

#include <sys/poll.h>
int poll (struct pollfd *fds, unsigned int nfds,
int timeout);

與上面的select()使用三個文件描述符集合不同,poll()使用了一個簡單的nfds個pollfd結構體構成的數組,fds指向該數組,結構體定義如下:

#include <sys/poll.h>
struct pollfd {int fd; /* file descriptor */short events; /* requested events to watch */short revents; /* returned events witnessed */
};

每個pollfd指定了唯一一個文件描述符,每個結構體中的events字段是要堅實的文件描述符事件的一組位掩碼。revents字段是發生在該文件描述符上的事件的位掩碼,內核在返回時設置這個字段,所有events字段請求的時間都可能在revents字段中返回。下面是合法的事件:

POLLIN       沒有數據可讀
POLLRDNORM   有正常數據可讀。
POLLRDBAND   有優先數據可讀。
POLLPRI      有高優先級數據可讀。
POLLOUT      寫操作不會阻塞。
POLLWRNORM   寫正常數據不會阻塞。
POLLBAND     寫優先數據不會阻塞。
POLLMSG      有一個sigpoll消息可用。

除此之外還可能返回幾個異常信息:

POLLER       文件描述符有錯誤。
POLLHUP      文件描述符上有掛起事件。
POLLNVAL     給出的文件描述符非法。

監視一個文件描述符是否可以讀寫,可以設置events為POLLIN | POLLOUT,返回時將在revents中檢查是否有相應標志。如果設置了POLLIN,或者POLLOUT則代表可以操作相關事件。

timeout參數指定在任何IO就緒前需要等待時間的長度,負值表示永遠等待,一個零值表示調用立即返回,列出所有為準備好的IO,不等待任何時間。

四、poll()與select()的區別

poll()系統調用優于select():

  • poll()不需要使用者計算最大的文件描述符值加一和傳遞該參數。
  • poll()在應對較大值的文件描述符時效率更好,如果用select()監視值為900的文件描述符–內核需要檢查每個集合中的每個bit位,知道第九百個。
  • select()的文件描述符集合是靜態大小,但是poll()可以創建合適大小的數組,只需要傳遞結構體數組即可。
  • select()文件描述符集合會在返回時重新創建,每個調用都必須要重新初始化它們。poll()系統調用分離了events字段和revents字段,無需改變就能重用。
  • 相對于poll(),select()移植性更好
  • select()提供了更好的超時方案。

五、epoll IO 多路復用

上面的兩種方式中,每次調用都需要所有被監聽的文件描述符,內核必須遍歷所有的文件描述符,當文件描述符變得很大,這里的遍歷就會成為瓶頸。

epoll將監聽注冊從實際監聽中分離出來,完成了真正的事件等待。

1、先創建一個新的epoll實例:

#include <sys/epoll.h>
int efpd =  epoll_create (int size)

size是告訴內核大概需要監聽的文件描述符數目。

2、控制epoll

epoll_ctl()可以向指定的epoll上下文中加入或刪除文件描述符。

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

頭文件

六、IO實現的內核內幕

主要涉及三個內核子系統:

  1. 虛擬文件系統(VFS)
  2. 頁緩存
  3. 頁回寫

虛擬文件系統

虛擬文件系統是linux內核的文件操作的抽象機制,允許內核在無需了解文件系統類型的情況下,使用文件系統函數和操作文件系統數據。

VFS實現這種抽象的方法是使用一種通用文件模型,它是所有linux文件系統的基礎,通用文件模型提供了linux內核文件系統必須遵循的框架,框架提供了了hooks支持讀寫、建立鏈接、同步等其他功能。

當然這種方法規定了一些共性,比如必須要有inode,super block(超級塊)和目錄條目等。

頁緩存

頁緩存是一種在內存中保存最近在磁盤文件系統上訪問過的數據的方式。頁緩存是內核尋找文件系統數據的第一目的地。只有緩存找不到時內核才會調用存儲子系統從磁盤讀數據。

linux中頁緩存大小是動態的,隨著IO操作將越來越多的數據帶入內存,頁緩存會隨之增大,消耗更多的內存,如果頁緩存確實消耗掉了所有空閑內存,頁緩存會釋放最少使用頁。

頁回寫

內核使用緩沖區來延遲寫操作,當一個進程發起寫請求,數據被拷貝到緩沖區,這時將緩沖區標記為“臟”數據,如果對同一個數據塊有新的寫請求,緩沖區就更新為新數據,把“臟”緩沖區寫入磁盤。有兩個條件會觸發這種回寫:

  1. 當空閑內存小于設定的閥值,會將緩沖區回寫。
  2. 當一個臟的緩沖區壽命超過閥值也會回寫防止數據不確定。

回寫由一些pdflush內核線程操作,當上述兩種情況發生,線程被喚醒開始刷新臟緩沖區。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384356.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384356.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384356.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

leetcode(一)刷題兩數之和

給定一個整數數組 nums 和一個整數目標值 target&#xff0c;請你在該數組中找出 和為目標值 target 的那 兩個 整數&#xff0c;并返回它們的數組下標。 示例 1&#xff1a; 輸入&#xff1a;nums [2,7,11,15], target 9 輸出&#xff1a;[0,1] 解釋&#xff1a;因為 nums[…

Linux并發服務器編程之多線程并發服務器

轉載&#xff1a;http://blog.csdn.net/qq_29227939/article/details/53782198 上一篇文章使用fork函數實現了多進程并發服務器&#xff0c;但是也提到了一些問題&#xff1a; fork是昂貴的。fork時需要復制父進程的所有資源&#xff0c;包括內存映象、描述字等&#xff1b;目…

leetcode(二)二分法查找算法

給定一個 n 個元素有序的&#xff08;升序&#xff09;整型數組 nums 和一個目標值 target &#xff0c;寫一個函數搜索 nums 中的 target&#xff0c;如果目標值存在返回下標&#xff0c;否則返回 -1。 示例 1: 輸入: nums [-1,0,3,5,9,12], target 9 輸出: 4 解釋: 9 出現在…

leetcode(977)有序數組的平方

給你一個按 非遞減順序 排序的整數數組 nums&#xff0c;返回 每個數字的平方 組成的新數組&#xff0c;要求也按 非遞減順序 排序。 示例 1&#xff1a; 輸入&#xff1a;nums [-4,-1,0,3,10] 輸出&#xff1a;[0,1,9,16,100] 解釋&#xff1a;平方后&#xff0c;數組變為 […

IO多路復用之select全面總結(必看篇)

轉載&#xff1a;http://www.jb51.net/article/101057.htm 1、基本概念 IO多路復用是指內核一旦發現進程指定的一個或者多個IO條件準備讀取&#xff0c;它就通知該進程。IO多路復用適用如下場合&#xff1a; &#xff08;1&#xff09;當客戶處理多個描述字時&#xff08;一般…

leetcode(189) 旋轉數組

**給定一個數組&#xff0c;將數組中的元素向右移動 k 個位置&#xff0c;其中 k 是非負數。 進階&#xff1a; 盡可能想出更多的解決方案&#xff0c;至少有三種不同的方法可以解決這個問題。 你可以使用空間復雜度為 O(1) 的 原地 算法解決這個問題嗎&#xff1f; 示例 1: …

I/O 多路復用之select

轉載&#xff1a;http://blog.csdn.net/u012432778/article/details/47347133 概述 Linux提供了三種 I/O 多路復用方案&#xff1a;select&#xff0c;poll和epoll。在這一篇博客里先討論select, poll 在將下一篇中介紹&#xff0c;epoll是Linux特有的高級解決方案&#xff0c;…

leetcode(283)移動零

283. 移動零 給定一個數組 nums&#xff0c;編寫一個函數將所有 0 移動到數組的末尾&#xff0c;同時保持非零元素的相對順序。 示例: 輸入: [0,1,0,3,12] 輸出: [1,3,12,0,0] 說明: 必須在原數組上操作&#xff0c;不能拷貝額外的數組。 盡量減少操作次數。 方法一&#xff1…

exec函數族實例解析

轉載&#xff1a;http://www.cnblogs.com/blankqdb/archive/2012/08/23/2652386.html fork()函數通過系統調用創建一個與原來進程(父進程)幾乎完全相同的進程(子進程是父進程的副本&#xff0c;它將獲得父進程數據空間、堆、棧等資源的副本。注意&#xff0c;子進程持有的是上述…

leetcode(167)兩數之和 II - 輸入有序數組

兩數之和 II - 輸入有序數組 給定一個已按照 升序排列 的整數數組 numbers &#xff0c;請你從數組中找出兩個數滿足相加之和等于目標數 target 。 函數應該以長度為 2 的整數數組的形式返回這兩個數的下標值。numbers 的下標 從 1 開始計數 &#xff0c;所以答案數組應當滿足 …

常量指針與指針常量的區別(轉帖)

轉載&#xff1a;http://www.cnblogs.com/witty/archive/2012/04/06/2435311.html 三個名詞雖然非常繞嘴&#xff0c;不過說的非常準確。用中國話的語義分析就可以很方便地把三個概念區分開。 一) 常量指針。 常量是形容詞&#xff0c;指針是名詞&#xff0c;以指針為中心的一個…

c/c++錯題總結

1.類名 對象名 默認調用“對象名()”這個構造函數&#xff0c;在棧內存中存在對象名&#xff0c;在堆內存中存在實際對象&#xff1b; 2.類名 對象名(一個或以上個參數) 默認調用相應的構造函數&#xff0c;在棧內存中存在對象名&#xff0c;在堆內存中也是存在實際對象的&a…

智能指針學習筆記

轉載&#xff1a;http://www.cnblogs.com/wuchanming/p/4411878.html 1. 介紹 本文介紹智能指針的使用。智能指針是c 中管理資源的一種方式&#xff0c;用智能指針管理資源&#xff0c;不必擔心資源泄露&#xff0c;將c 程序員 從指針和內存管理中解脫出來&#xff0c;再者&…

c++程序編譯過程

c程序編譯分成四個過程&#xff1a;編譯預處理&#xff0c;編譯&#xff0c;匯編&#xff0c;鏈接 編譯預處理&#xff1a;處理以#為開頭 編譯&#xff1a;將.cpp文件翻譯成.s匯編文件 匯編&#xff1a;將.s匯編文件翻譯成機器指令.o文件 鏈接&#xff1a;匯編生產的目標文件.o…

仿函數(函數對象)

轉載&#xff1a;http://www.cnblogs.com/wuchanming/p/4411867.html 本文乃作者學習《C標準程序庫》的學習筆記&#xff0c;首先介紹了仿函數&#xff08;函數對象&#xff09;和函數適配器&#xff08;配接器&#xff09;的概念&#xff0c;然后列出STL中所有的仿函數&#x…

C++ template —— 動多態與靜多態(六)

轉載&#xff1a;http://www.cnblogs.com/yyxt/p/5157517.html 前面的幾篇博文介紹了模板的基礎知識&#xff0c;并且也深入的講解了模板的特性。接下來的博文中&#xff0c;將會針對模板與設計進行相關的介紹。 ------------------------------------------------------------…

變量之間的區別

全局變量、局部變量、靜態全局變量、靜態局部變量的區別 c變量根據定義具有不同的生命周期&#xff0c;會有不同的作用域&#xff0c;主要有六個作用域&#xff1a;全局作用域&#xff0c;局部作用域&#xff0c;文件作用域&#xff0c;類作用域&#xff0c;語句作用域&#xf…

計算機的網絡體系以及參考模型

計算機的網絡體系以及參考模型一、OSI七層模型二、TCP/IP參考模型三、TCP/IP 五層參考模型四、OSI 模型和 TCP/IP 模型異同比較五、OSI 和 TCP/IP 協議之間的對應關系六、為什么 TCP/IP 去除了表示層和會話層&#xff1f;七、數據如何在各層之間傳輸&#xff08;數據的封裝過程…

C++ 模板詳解(二)

轉載&#xff1a;http://www.cnblogs.com/gw811/archive/2012/10/25/2736224.html 四、類模板的默認模板類型形參 1、可以為類模板的類型形參提供默認值&#xff0c;但不能為函數模板的類型形參提供默認值。函數模板和類模板都可以為模板的非類型形參提供默認值。 2、類模板的類…

c++類對象的創建方式

對象創建限制在堆或棧 c類對象的創建方式對象創建限制在堆或棧C 中的類的對象的建立模式如何將類限制在堆上呢&#xff1f;C 中的類的對象的建立模式 C 中的類的對象的建立模式分為兩張&#xff1a;靜態建立&#xff0c;動態建立 靜態建立&#xff1a;由編譯器為對象在棧空間…