一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

【系統(tǒng)編程】五種IO模型分析

 太極混元天尊 2018-05-23

作者:駿馬金龍

鏈接:http://www.cnblogs.com/f-ck-need-u/

碼農有道作了部分修改

碼農有道

 

歷史文章目錄(請戳我)

關于碼農有道(請戳我)


網絡數(shù)據(jù)傳輸時經歷了哪些buffer(請戳我)一文中主要總結了從客戶端發(fā)起一個http請求,網絡數(shù)據(jù)的流向,有了上文的基礎,本文再來講講五種I/O模型。

所謂的IO模型,描述的是出現(xiàn)I/O等待時進程的狀態(tài)以及處理數(shù)據(jù)的方式。圍繞著進程的狀態(tài)、數(shù)據(jù)準備到kernel buffer再到app buffer的兩個階段展開。其中數(shù)據(jù)復制到kernel buffer的過程稱為數(shù)據(jù)準備階段,數(shù)據(jù)從kernel buffer復制到app buffer的過程稱為數(shù)據(jù)復制階段。請記住這兩個概念,后面描述I/O模型時會一直用這兩個概念。

本文以httpd進程的TCP連接方式處理本地文件為例,請無視httpd是否真的實現(xiàn)了如此、那般的功能,也請無視TCP連接處理數(shù)據(jù)的細節(jié),這里僅僅只是作為方便解釋的示例而已。另外,本文用本地文件作為I/O模型的對象不是很適合,它的重頭戲是在套接字上,

再次說明:從硬件設備到內存的數(shù)據(jù)傳輸過程是不需要CPU參與的,而內存間傳輸數(shù)據(jù)是需要CPU參與的。


Blocking I/O模型

如圖:

假設客戶端發(fā)起index.html的文件請求,httpd需要將index.html的數(shù)據(jù)從磁盤中加載到自己的httpd app buffer中,然后復制到send buffer中發(fā)送出去。

但是在httpd想要加載index.html時,它首先檢查自己的app buffer中是否有index.html對應的數(shù)據(jù),沒有就發(fā)起系統(tǒng)調用讓內核去加載數(shù)據(jù),例如read(),內核會先檢查自己的kernel buffer中是否有index.html對應的數(shù)據(jù),如果沒有,則從磁盤中加載,然后將數(shù)據(jù)準備到kernel buffer,再復制到app buffer中,最后被httpd進程處理。

如果使用Blocking I/O模型:

1當設置為blocking i/o模型,httpd從都是被阻塞的。

2只有當數(shù)據(jù)復制到app buffer完成后,或者發(fā)生了錯誤,httpd才被喚醒處理它app buffer中的數(shù)據(jù)。

3cpu會經過兩次上下文切換:用戶空間到內核空間再到用戶空間。

4由于階段的拷貝是不需要CPU參與的,所以在階段準備數(shù)據(jù)的過程中,cpu可以去處理其它進程的任務。

5階段的數(shù)據(jù)復制需要CPU參與,將httpd阻塞,在某種程度上來說,有助于提升它的拷貝速度。

如下圖:



Non-Blocking I/O模型

如果使用Non-Blocking I/O模型:

1.當設置為non-blocking時,httpd第一次發(fā)起系統(tǒng)調用(如read())后,立即返回一個錯誤值EWOULDBLOCK(至于read()讀取一個普通文件時能否返回EWOULDBLOCK請無視,畢竟I/O模型主要是針對套接字文件的,就當read()是recv()好了),而不是讓httpd進入睡眠狀態(tài)。

2雖然read()立即返回了,但httpd還要不斷地去發(fā)送read()檢查內核:數(shù)據(jù)是否已經成功拷貝到kernel buffer了?這稱為輪詢(polling)。每次輪詢時,只要內核沒有把數(shù)據(jù)準備好,read()就返回錯誤信息EWOULDBLOCK。

3直到kernel buffer中數(shù)據(jù)準備完成,再去輪詢時不再返回EWOULDBLOCK,而是將httpd阻塞,以等待數(shù)據(jù)復制到app buffer。

4httpd在階段不被阻塞,但是會不斷去發(fā)送read()輪詢。在被阻塞,將cpu交給內核把數(shù)據(jù)copy到app buffer。

如下圖:



I/O Multiplexing

稱為多路IO模型IO復用,意思是可以檢查多個IO等待的狀態(tài)。有三種IO復用模型:selectpollepoll。其實它們都是一種函數(shù),用于監(jiān)控指定文件描述符的數(shù)據(jù)是否就緒,就緒指的是對某個系統(tǒng)調用不再阻塞了,例如對于read()來說,就是數(shù)據(jù)準備好了就是就緒狀態(tài)。

就緒種類包括是否可讀、是否可寫以及是否異常,其中可讀條件中就包括了數(shù)據(jù)是否準備好。當就緒之后,將通知進程,進程再發(fā)送對數(shù)據(jù)操作的系統(tǒng)調用,如read()。所以,這三個函數(shù)僅僅只是處理了數(shù)據(jù)是否準備好以及如何通知進程的問題??梢詫⑦@幾個函數(shù)結合阻塞和非阻塞IO模式使用,例如設置為非阻塞時,select()/poll()/epoll將不會阻塞在對應的描述符上,調用函數(shù)的進程/線程也就不會被阻塞。

如果使用I/O Multiplexing模型:

1當想要加載某個文件時,假如httpd要發(fā)起read()系統(tǒng)調用,如果是阻塞或者非阻塞情形,那么read()會根據(jù)數(shù)據(jù)是否準備好而決定是否返回,是否可以主動去監(jiān)控這個數(shù)據(jù)是否準備到了kernel buffer中呢,亦或者是否可以監(jiān)控send buffer中是否有新數(shù)據(jù)進入呢?這就是select()/poll()/epoll的作用。

2當使用select()時,httpd發(fā)起一個select調用,然后httpd進程被select()'阻塞'。由于此處假設只監(jiān)控了一個請求文件,所以select()會在數(shù)據(jù)準備到kernel buffer中時直接喚醒httpd進程。之所以阻塞要加上雙引號,是因為select()有時間間隔選項可用控制阻塞時長,如果該選項設置為0,則select不阻塞,此時表示立即返回但一直輪詢檢查是否就緒,還可以設置為永久阻塞。

3當select()的監(jiān)控對象就緒時,將通知(輪詢情況)或喚醒(阻塞情況)httpd進程,httpd再發(fā)起read()系統(tǒng)調用,此時數(shù)據(jù)會從kernel buffer復制到app buffer中并read()成功。

4httpd發(fā)起第二個系統(tǒng)調用(即read())后被阻塞,CPU全部交給內核用來復制數(shù)據(jù)到app buffer。 (5).對于httpd只處理一個連接的情況下,IO復用模型還不如blocking I/O模型,因為它前后發(fā)起了兩個系統(tǒng)調用(即select()和read()),甚至在輪詢的情況下會不斷消耗CPU。但是IO復用的優(yōu)勢就在于能同時監(jiān)控多個文件描述符。

如圖:



Signal-driven I/O模型

信號驅動IO模型。當開啟了信號驅動功能時,首先發(fā)起一個信號處理的系統(tǒng)調用,如sigaction(),這個系統(tǒng)調用會立即返回。但數(shù)據(jù)在準備好時,會發(fā)送SIGIO信號,進程收到這個信號就知道數(shù)據(jù)準備好了,于是發(fā)起操作數(shù)據(jù)的系統(tǒng)調用,如read()。

在發(fā)起信號處理的系統(tǒng)調用后,進程不會被阻塞,但是在read()將數(shù)據(jù)從kernel buffer復制到app buffer時,進程是被阻塞的。如圖:



Asynchronous I/O模型

異步IO模型。當設置為異步IO模型時,httpd首先發(fā)起異步系統(tǒng)調用(如aio_read(),aio_write()等),并立即返回。這個異步系統(tǒng)調用告訴內核,不僅要準備好數(shù)據(jù),還要把數(shù)據(jù)復制到app buffer中。

httpd從返回開始,直到數(shù)據(jù)復制到app buffer結束都不會被阻塞。當數(shù)據(jù)復制到app buffer結束,將發(fā)送一個信號通知httpd進程。

如圖:

看上去異步很好,但是注意,在復制kernel buffer數(shù)據(jù)到app buffer中時是需要CPU參與的,這意味著不受阻的httpd會和異步調用函數(shù)爭用CPU。如果并發(fā)量比較大,httpd接入的連接數(shù)可能就越多,CPU爭用情況就越嚴重,異步函數(shù)返回成功信號的速度就越慢。如果不能很好地處理這個問題,異步IO模型也不一定就好。


同步I/O與異步I/O,阻塞與非阻塞區(qū)別

阻塞、非阻塞、IO復用、信號驅動都是同步IO模型。因為在發(fā)起操作數(shù)據(jù)的系統(tǒng)調用(如本文的read())過程中是被阻塞的。這里要注意,雖然在加載數(shù)據(jù)到kernel buffer的數(shù)據(jù)準備過程中可能阻塞、可能不阻塞,但kernel buffer才是read()函數(shù)的操作對象,同步的意思是讓kernel buffer和app buffer數(shù)據(jù)同步。顯然,在保持kernel buffer和app buffer同步的過程中,進程必須被阻塞,否則read()就變成異步的read()。

只有異步IO模型才是異步的,因為發(fā)起的異步類的系統(tǒng)調用(如aio_read())已經不管kernel buffer何時準備好數(shù)據(jù)了,就像后臺一樣read一樣,aio_read()可以一直等待kernel buffer中的數(shù)據(jù),在準備好了之后,aio_read()自然就可以將其復制到app buffer。

如圖:


    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    内射精品欧美一区二区三区久久久| 免费在线播放一区二区| 日韩国产中文在线视频| 国产色一区二区三区精品视频| 麻豆蜜桃星空传媒在线观看| 成在线人免费视频一区二区| 亚洲黄香蕉视频免费看| 日韩欧美国产高清在线| 国产精品亚洲综合天堂夜夜| 麻豆果冻传媒一二三区| 久热99中文字幕视频在线| 在线一区二区免费的视频| 欧美一级黄片欧美精品| 欧美精品久久一二三区| 国产亚洲视频香蕉一区| 大香蕉久草网一区二区三区| 国产精品欧美日韩中文字幕| 国产成人精品午夜福利av免费| 老外那个很粗大做起来很爽| 国产精欧美一区二区三区久久| 欧美精品日韩精品一区| 国产日韩欧美一区二区| 国产一区二区三区av在线| 日本熟女中文字幕一区| 高清欧美大片免费在线观看| 人妻中文一区二区三区| 91精品视频免费播放| 色鬼综合久久鬼色88| 视频一区二区 国产精品| 国产自拍欧美日韩在线观看| 国产老女人性生活视频| 日韩人妻中文字幕精品| 亚洲一区二区三区国产| 国产欧美日产久久婷婷| 日韩熟妇人妻一区二区三区| 国产精品白丝一区二区| 亚洲熟女国产熟女二区三区| 成人国产激情在线视频| 福利视频一区二区三区| 色偷偷亚洲女人天堂观看| 精品日韩av一区二区三区|