Linux/Unix五種I/O模型
- 内容來源,侵删。
- 遊雙-《Linux高性能伺服器程式設計》
- 牛客網-Linux高并發伺服器開發
阻塞-blocking
- 調用者調用了某個函數,然後等待這個函數傳回,在這期間
,
什麼都不做
,應用程式必須等這個函數傳回才能進行下一步的動作。
不停的去檢查這個函數有沒有傳回
- 即,針對阻塞I/O執行的系統調用可能因為無法立即完成而被作業系統
,直到等待的時間發生為止,才可以繼續執行下一步的操作。
挂起
- 可能被阻塞的系統調用包括accept、send、recv、connect。
非阻塞-non blocking (NIO)
-
,若事件沒有發生,則傳回-1,此時可以根據errno區分這兩種情況,對于accept、recv和send、事件未發生時,errno通常被設定成
非阻塞I/O執行系統調用總是立即傳回,不管事件是否已經發生
。
EAGAIN
- 我們隻有在事件已經發生的情況下操作非阻塞I/O,才能提高程式的效率。是以,
,比如I/O多路複用和SIGIO信号。
非阻塞I/O通常要和其它I/O通知機制一起使用
I/O複用-IO multiplexing
-
。
I/O多路複用是最常用的I/O通知機制
- 它指的是:
。
應用程式通過I/O複用函數向核心注冊一組事件,核心通過I/O複用函數把其中就緒的事件通知給應用程式
- 在單程序/線程的情況下,可以檢測多個客戶的事件是否發生。
- I/O複用函數本身也是阻塞的,它們能提高程式效率的原因在于它們
。
可以同時監聽多個I/O事件
- 單單使用I/O多路複用并不能處理高并發,而要處理高并發還是需要結合多程序/線程。
信号驅動-signal driven
- 為某一程序安裝一個信号處理函數,程序運作,當I/O事件就緒,該程序收到SIGIO信号,然後開始處理I/O事件。
- 我們可以為目标檔案描述符指定宿主程序,被指定的宿主程序将捕獲到SIGIO信号,當目标問檔案名描述符上有事件發生時,SIGIO信号的信号處理函數将被觸發,我們可
。
在該信号處理函數中對目标檔案描述符執行非阻塞I/O操作
- 核心在第一個階段是
,在第二個階段是
異步
;信号驅動I/O與非阻塞I/O的差別在于它提供了
同步
,不需要使用者程序不斷的輪詢檢查,減少了系統調用的次數,提高了效率。
消息通知機制
- 補充:
- 同步與異步:
——來源線程與同步異步
同步是執行或調用一個方法時,每次都需要拿到對應的結果才會繼續往後執行;異步與同步相反,它會在執行或調用一個方法後就繼續往後執行,不會等待擷取執行結果。二者的差別就是處理請求發出後,是否需要等待請求結果,再去繼續執行其他操作。
異步I/O-asynchronous
- 從理論上來講,阻塞I/O、I/O複用和信号驅動I/O都是
模型,因為在這三種I/O模型中,I/O的讀寫操作,都是在I/O事件發生之後,由應用程式來完成的。
同步I/O
- 對異步I/O而言,使用者可以
,這些操作告訴核心使用者讀寫緩沖區的位置,以及I/O操作完成之後核心通知應用程式的方式。(POSIX規範)
直接對I/O執行讀寫操作
- 在Linux中,每次調用aio_read函數告訴核心描數字緩沖區指針和緩沖區的大小、檔案偏移及通知的方式,然後立即傳回,當核心将資料拷貝到緩沖區後,再通知應用程式。
- 異步I/O的讀寫操作總是立即傳回,無論I/O是否阻塞,因為
。
真正的讀寫操作已由核心接管
- 對比:
- 同步I/O模型要求
(将資料從使用者緩沖區拷貝到核心緩沖區,從核心緩沖區拷貝到使用者緩沖區)。
使用者代碼自行執行I/O操作
- 異步I/O則是由
(即資料在使用者緩沖區域核心緩沖區的移動是由核心在"背景"完成的)。
核心來執行I/O操作
- 可以這樣了解:
- 同步I/O向應用程式通知的是I/O
。
就緒事件
- 異步I/O向應用程式通知的是I/O
。
完成事件