如何切換鼠標(如何切換鼠標模式)
641
2022-05-29
5種IO模型、阻塞IO和非阻塞IO、同步IO和異步IO
看了一些文章,發現有很多不同的理解,可能是因為大家入切的角度、環境不一樣。所以,我們先說明基本的IO操作及環境。
本文是在《UNIX網絡編程 卷1:套接字聯網API》6.2節"I/O 模型 "的基礎上,即UNIX/LINUX環境下的網絡 IO環境下的理解,它里面給出的例子是讀取(接收)網絡UDP數據。下面簡單寫寫自己對這些IO模型的理解。
1、IO
IO (Input/Output,輸入/輸出)即數據的讀取(接收)或寫入(發送)操作,通常用戶進程中的一個完整IO分為兩階段:用戶進程空間<–>內核空間、內核空間<–>設備空間(磁盤、網絡等)。IO有內存IO、網絡IO和磁盤IO三種,通常我們說的IO指的是后兩者。
LINUX中進程無法直接操作I/O設備,其必須通過系統調用請求kernel來協助完成I/O動作;內核會為每個I/O設備維護一個緩沖區。
對于一個輸入操作來說,進程IO系統調用后,內核會先看緩沖區中有沒有相應的緩存數據,沒有的話再到設備中讀取,因為設備IO一般速度較慢,需要等待;內核緩沖區有數據則直接復制到進程空間。
所以,對于一個網絡輸入操作通常包括兩個不同階段:
等待網絡數據到達網卡→讀取到內核緩沖區,數據準備好;
從內核緩沖區復制數據到進程空間。
2、5種IO模型
《UNIX網絡編程》說得很清楚,5種IO模型分別是阻塞IO模型、非阻塞IO模型、IO復用模型、信號驅動的IO模型、異步IO模型;前4種為同步IO操作,只有異步IO模型是異步IO操作。
下面這樣些圖,是它里面給出的例子:接收網絡UDP數據的流程在IO模型下的分析,在它的基礎上再加以簡單描述,以區分這些IO模型。搜索Java知音公眾號,回復“后端面試”,送你一份Java面試題寶典
2-1、阻塞IO模型
進程發起IO系統調用后,進程被阻塞,轉到內核空間處理,整個IO處理完畢后返回進程。操作成功則進程獲取到數據。
進程阻塞掛起不消耗CPU資源,及時響應每個操作;
實現難度低、開發應用較容易;
適用并發量小的網絡應用開發;
不適用并發量大的應用:因為一個請求IO會阻塞進程,所以,得為每請求分配一個處理進程(線程)以及時響應,系統開銷大。
2-2、非阻塞IO模型
進程發起IO系統調用后,如果內核緩沖區沒有數據,需要到IO設備中讀取,進程返回一個錯誤而不會被阻塞;進程發起IO系統調用后,如果內核緩沖區有數據,內核就會把數據返回進程。
對于上面的阻塞IO模型來說,內核數據沒準備好需要進程阻塞的時候,就返回一個錯誤,以使得進程不被阻塞。搜索Java知音公眾號,回復“后端面試”,送你一份Java面試題寶典
進程輪詢(重復)調用,消耗CPU的資源;
實現難度低、開發應用相對阻塞IO模式較難;
適用并發量較小、且不需要及時響應的網絡應用開發;
2-3、IO復用模型
多個的進程的IO可以注冊到一個復用器(select)上,然后用一個進程調用該select, select會監聽所有注冊進來的IO;
如果select沒有監聽的IO在內核緩沖區都沒有可讀數據,select調用進程會被阻塞;而當任一IO在內核緩沖區中有可數據時,select調用就會返回;
而后select調用進程可以自己或通知另外的進程(注冊進程)來再次發起讀取IO,讀取內核中準備好的數據。
可以看到,多個進程注冊IO后,只有另一個select調用進程被阻塞。
專一進程解決多個進程IO的阻塞問題,性能好;Reactor模式;
實現、開發應用難度較大;
適用高并發服務應用開發:一個進程(線程)響應多個請求;
3、select、poll、epoll
Linux中IO復用的實現方式主要有select、poll和epoll:
Select:注冊IO、阻塞掃描,監聽的IO最大連接數不能多于FD_SIZE;
Poll:原理和Select相似,沒有數量限制,但IO數量大掃描線性性能下降;
Epoll :事件驅動不阻塞,mmap實現內核與用戶空間的消息傳遞,數量很大,Linux2.6后內核支持;
2-4、信號驅動IO模型
當進程發起一個IO操作,會向內核注冊一個信號處理函數,然后進程返回不阻塞;當內核數據就緒時會發送一個信號給進程,進程便在信號處理函數中調用IO讀取數據。
2-5、異步IO模型
當進程發起一個IO操作,進程返回(不阻塞),但也不能返回果結;內核把整個IO處理完后,會通知進程結果。如果IO操作成功則進程直接獲取到數據。
不阻塞,數據一步到位;Proactor模式;
需要操作系統的底層支持,LINUX 2.5 版本內核首現,2.6 版本產品的內核標準特性;
實現、開發應用難度大;
非常適合高性能高并發應用;
3、IO模型比較
注意這里的阻塞IO調用和非阻塞IO調用不是指阻塞IO模型和非阻塞IO模型:
阻塞IO調用 :在用戶進程(線程)中調用執行的時候,進程會等待該IO操作,而使得其他操作無法執行。
非阻塞IO調用:在用戶進程中調用執行的時候,無論成功與否,該IO操作會立即返回,之后進程可以進行其他操作(當然如果是讀取到數據,一般就接著進行數據處理)。
這個直接理解就好,進程(線程)IO調用會不會阻塞進程自己。所以這里兩個概念是相對調用進程本身狀態來講的。
從上面對比圖片來說,阻塞IO模型是一個阻塞IO調用,而非阻塞IO模型是多個非阻塞IO調用+一個阻塞IO調用,因為多個IO檢查會立即返回錯誤,不會阻塞進程。
而上面也說過了,非阻塞IO模型對于阻塞IO模型來說區別就是,內核數據沒準備好需要進程阻塞的時候,就返回一個錯誤,以使得進程不被阻塞。
3-2、同步IO和異步IO
同步IO:導致請求進程阻塞,直到I/O操作完成。
異步IO:不導致請求進程阻塞。
上面兩個定義是《UNIX網絡編程 卷1:套接字聯網API》給出的。這不是很好理解,我們來擴展一下,先說說同步和異步,同步和異步關注的是雙方的消息通信機制:
同步:雙方的動作是經過雙方協調的,步調一致的。
異步:雙方并不需要協調,都可以隨意進行各自的操作。
這里我們的雙方是指,用戶進程和IO設備;明確同步和異步之后,我們在上面網絡輸入操作例子的基礎上,進行擴展定義:
同步IO:用戶進程發出IO調用,去獲取IO設備數據,雙方的數據要經過內核緩沖區同步,完全準備好后,再復制返回到用戶進程。而復制返回到用戶進程會導致請求進程阻塞,直到I/O操作完成。
異步IO:用戶進程發出IO調用,去獲取IO設備數據,并不需要同步,內核直接復制到進程,整個過程不導致請求進程阻塞。
所以, 阻塞IO模型、非阻塞IO模型、IO復用模型、信號驅動的IO模型者為同步IO模型,只有異步IO模型是異步IO。
任務調度 Java
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。