IO模式 select、poll、epoll

阻塞(blocking)、非阻塞(non-blocking):最常聽到阻塞與非阻塞這兩個詞就是在函數調用中,好比waitid這個函數,經過NOHANG參數能夠把waitid設置爲非阻塞的,也就是問詢一遍子進程,看看有沒有可回收子進程,若是沒有,直接返回不等待,而若是不設置NOHANG,waitid會一直問詢子進程,直到有一個可回收子進程再返回,也就是說若是沒有子進程可回收,waitid會一直阻塞在這條函數調用上,後面的操做就沒法執行。若是把函數調用籠統的規劃到一個事件的執行,那麼阻塞與非阻塞的區別就是 是否僅僅只等待事件完成(事件返回)才進行下一步操做。好比 燒開水這個例子(參考資料中有提到),若是人從水壺開始燒水到水燒開這段時間一直在水壺前等待燒水,這就是阻塞,若是人比較聰明,在水壺燒水的過程當中,人去看電視了或者幹其餘事情了,這就是不阻塞的,可是在這種狀況下,人想要知道水是否燒開了,只能隔一段時間去看一下水壺「燒開了沒有?」,這個隔一段時間去看一下的方法 就是 輪詢。因此,再回到waitid這個例子,咱們設置NOHANG參數的時候,通常都要在waitid上加一個用於輪詢的循環。編程

同步(synchronous)、異步(asynchronous):同步和異步,一開始看很容易把同步和阻塞的概念混淆在一塊兒,我傾向於將同步理解爲一種現象,而阻塞/非阻塞做爲這個現象中的某種狀態存在。同步和異步的區別,參考資料中的說法我以爲雖然把同步異步區別說出來了,可是同步和阻塞仍是很容易混淆。那我再對燒開水這個例子重寫一下以供參考,水壺分爲 普通水壺 和 智能水壺,普通水壺須要人手工操做,須要人判斷水是否燒開,水燒開了須要人把水壺從火上拿下來(否則會溢出來),而智能水壺提供兩個做用,水燒開後自動關火而且發出響聲提示人水已經燒好。燒開水就分爲了兩個過程,等待水開和拿開水壺,首先說同步和異步,同步就是使用普通水壺燒水,水燒開後須要人主動拿開水壺,而等待水燒開的這個過程能夠是阻塞(站那等)的和非阻塞(看電視輪詢)的,整個操做須要人的全程參與;異步就是使用智能水壺燒水,等待水開的過程人能夠幹任何事(即異步自己就是非阻塞的,因此異步並不區分阻塞/非阻塞)而且人不用關心水是否燒開(敲重點),水燒開後,智能水壺會發出響聲提示人(發出信號),這完成了等待水開這第一過程,緊接着,智能水壺會自動關火,這代替了人拿開水壺的這個動做完成了第二過程。能夠發現,同步整個過程須要人全程參與,而異步整個過程是兩個「人」在作,一個「人」就是這個智能水壺,一我的就是始終在作其餘事的人,這我的將燒開水這件事託管給了智能水壺由智能水壺完成一切過程,最後提示人完成了。所以,判斷同步只須要看,事件的監管和完成方是否是事件發起者便可。網絡

在接下來即將要說到的IO操做中,異步IO就是進程將IO操做徹底交由內核控制,由內核中的DMA控制器完成所有IO操做並在完成後經過信號提示進程IO操做已完成,這也是兩個「人」的事情,進程將IO託管給DMA控制器,而進程又能夠幹其餘的事,兩者在不一樣的事件上各自執行操做,是並行的。異步

IO模式:async

好比對於一個read操做發生時,它會經歷下面兩個階段:ide

A, 等待數據準備,數據是否拷貝到內核緩衝區;函數

B, 將數據從內核拷貝到用戶進程空間spa

若是把這兩個階段對應到前文中我寫的燒開水的兩個過程當中,對於下面的幾種IO模式就容易理解的多。線程

《Unix網絡編程卷1:套接字聯網API》(即UNP)中第六章對unix 系統將IO模型分爲五類:阻塞IO,非阻塞IO,IO複用,信號驅動,異步IOunix

一、阻塞IO:A階段阻塞等待,進程調用recvfrom詢問內核數據是否準備好,直到數據準備好再返回。(注意:由內核監聽數據,進程詢問內核數據是否準備好)視頻

二、非阻塞IO:A階段非阻塞等待,即採用輪詢機制(即進程不斷的詢問內核數據是否準備好(不斷調用recvfrom),這麼作每每消耗大量CPU時間)判斷數據是否拷貝到內核緩衝區。

三、IO複用:IO複用技術是對阻塞IO的改進,首先非阻塞大量消耗CPU,不予考慮。在數據準備階段,內核監聽一個IO也好,監聽一羣IO也好,都在監聽,所以複用,就是內核同時監聽進程的多個IO操做,在進程詢問時返回有數據到來的IO。此時進程不是阻塞在recvfrom上,而是阻塞在IO複用系統調用——select、poll、epoll上,這幾個系統調用會在所監聽的全部IO中某個或某幾個有數據到來時返回。

多路IO共用一個同步阻塞接口,任意IO可操做均可激活IO操做,這是對阻塞IO的改進(主要是select和poll、epoll,關鍵是能實現同時對多個IO端口進行監聽)。此時阻塞發生在select/poll的系統調用上,而不是阻塞在實際的I/O系統調用上。IO多路複用的高級之處在於:它能同時等待多個文件描述符,而這些文件描述符(套接字描述符)其中的任意一個進入讀就緒狀態,select等函數就能夠返回。

四、信號驅動

註冊一個IO信號事件,在數據可操做時經過SIGIO信號通知線程,這應該算是一種異步機制;

五、異步IO:進程通知內核完成一個IO操做,由內核完成A+B階段後通知進程。

參考中的這張圖很好的解釋了上述5種IO模型。

 

 

 

POSIX將IO只分紅了同步IO、異步IO兩種模型。

同步I/O操做:實際的I/O操做將致使請求進程阻塞,直到I/O操做完成。

異步I/O操做:實際的I/O操做不致使請求進程阻塞。

由此,阻塞式I/O,非阻塞式I/O,I/O複用,信號驅動I/O模型都屬於同步I/O,由於第二階段的數據複製都是阻塞的,也能夠理解爲都由進程完成。而只有異步I/O模型屬於這裏的異步I/O操做(IO由內核完成)。

參考資料:知乎Linux分享官

bilibili視頻

《Unix網絡編程卷1:套接字聯網API(第3版)》6.2 IO模型

相關文章
相關標籤/搜索