文章目錄
- IO模型
- 阻塞IO
- 非阻塞IO
- 信號驅動IO
- 多路復用IO
- 異步IO
IO模型
根據各自的特性不同,IO模型被分為阻塞IO、非阻塞IO、信號驅動IO、異步IO、多路復用IO五類。
最主要的兩個區別就是阻塞與非阻塞,同步與異步。
阻塞與非阻塞
阻塞與非阻塞最主要的區別就是程序在等待調用結果時的狀態。
- 阻塞: 為了完成一個功能發起調用,如果不具備完成功能的條件,則調用會一直等待
- 非阻塞: 為了完成一個功能發起調用,如果不具備完成功能的條件,則立即報錯返回
同步與異步
并發模型和I/O模型都有同步/異步的概念:
-
并發模式中兩者最主要的區別就是功能完成的流程是否是順序化的,
-
I/O模型中兩者最主要的區別是注冊的是就緒事件還是完成事件,完成I/O操作的是用戶程序自身還是內核系統。
-
同步: 功能完成的流程是順序化的。注冊就緒事件,讀寫事件由自身完成。
-
異步: 功能完成的流程是不確定的,注冊完成事件,讀寫事件由內核完成。
下列五種IO模型,從前往后處理的效率逐漸增加,對資源的利用也增加充分,但是流程也越來越復雜。
阻塞IO
發起IO調用,如果不具備IO條件,則一直等待直到條件就緒。以 recvfrom
為例:(recvfrom
:UDP數據的讀寫函數)
- 優點: 流程以及代碼實現都非常簡單,任務順序操作。
- 缺點: 任務處理效率較低,無法充分利用資源。
非阻塞IO
發起一個IO調用,如果不具備IO條件,則立即報錯返回(無需等待),繼續執行其他命令。通過一個循環來不斷發起IO請求,直到條件就緒。
- 優點: 與阻塞IO相比較來說,利用了等待的時間去做了其他的事情,對資源的利用更加充分。
- 缺點: 與阻塞IO對比,IO調用需要循環發起,流程更加復雜。 并且如果IO條件就緒了,也要等待同一個調用上一輪循環結束后進入當前循環,才能進行處理,這就導致了 IO 不夠實時。
非阻塞IO可以通過 fcntl函數
設置描述符狀態來實現:
void SetNoBlock(int fd)
{int flag = fcntl(fd, F_GETFL, 0);flag |= O_NONBLOCK;fcntl(fd, F_SETFL, flag);
}
信號驅動IO
自定義一個IO就緒的信號,當IO就緒時就發出這個信號。在沒有收到信號時,可以繼續處理其他事情,一旦收到信號,就會中斷當前操作,來優先處理IO事件。程序沒有阻塞階段。
- 優點: 相較于非阻塞IO,仍具有資源利用更加充分的優勢;并且信號到來后就直接強行中斷進行處理,更加實時。
- 缺點: 因為需要自定義信號,又要有主控流程也要有信號處理流程,并且還需要考慮信號是否可靠導致的事件丟失情況,流程會更加的復雜。
多路復用IO
用于對大量的IO事件進行監控,能夠讓用戶只針對就緒了指定事件(可讀、可寫、異常) 的IO進行操作。只針對就緒的描述符進行操作,避免了阻塞,并且提高了效率。
值得一提的是,I/O復用函數對I/O本身的讀寫操作是阻塞的,他們能提高程序效率的原因在于具有同時監聽多個I/O事件的能力。
在 Linux
下,操作系統提供了三種模型:select模型
、poll模型
、epoll模型
。
異步IO
IO處理的順序不確定,整個IO的過程(等待 + 數據拷貝)由操作系統來完成而并非用戶。程序沒有阻塞階段。
流程:
- 自定義一個IO完成信號
- 發起異步調用后返回,此時用戶可以繼續處理其他事情
- 系統進行IO事件的等待以及數據拷貝
- IO完成后通過信號通知進程IO
- 優點: 對資源的利用最為充分, 以最高的效率進行任務的處理。
- 缺點: 資源消耗較高, 流程最為復雜。