I/O模型

I/O模型

同步、異步、阻塞、非阻塞

同步與異步:描述的是用戶線程與內核的交互方式,同步指用戶線程發起IO請求後需要等待或者輪詢內核IO操作完成後才能繼續執行;而異步是指用戶線程發起IO請求後仍然繼續執行,當內核IO操作完成後會通知用戶線程,或者調用用戶線程註冊的回調函數。

阻塞與非阻塞:描述是用戶線程調用內核IO操作的方式,阻塞是指IO操作需要徹底完成後才返回到用戶空間;而非阻塞是指IO操作被調用後立即返回給用戶一個狀態值,無需等到IO操作徹底完成。

Linux IO模型

linux系統IO分爲內核準備數據和將數據從內核拷貝到用戶空間兩個階段。

網絡IO的本質就是socket的讀取,socket在linux系統被抽象爲流,IO可以理解爲對流的操作。對於一次IO訪問(以read爲例),數據會先被拷貝到操作系統內核的緩衝區,然後纔會從操作系統內核的緩衝區拷貝到應用程序的地址空間中。所以說,當一個read操作發生時,它會經歷兩個階段:

第一個階段:等待數據準備。

第二個階段:將數據從內核拷貝到進程中(把數據從內核空間拷貝到用戶空間)

對於socket流而言:

第一步:通常涉及等待網絡上的數據分組到達,然後複製到內核的某個緩衝區。

第二步:把數據從內核緩衝區複製到應用進程緩衝區。

當然,如果內核空間的緩衝區中已經有數據了,那麼就可以省略第一步。至於爲什麼不能直接讓磁盤控制器把數據送到應用程序的地址空間中呢?最簡單的一個原因就是應用程序不能直接操作底層硬件。

網絡應用需要處理的無非就是兩大類問題,網絡IO,數據計算。相對於後者,網絡IO的延遲,給應用帶來的性能瓶頸大於後者。網絡IO的模型大致分爲如下五種:

阻塞IO
非阻塞IO
多路複用IO
信號驅動IO
異步IO

前四種都是同步,只有最後一種是異步IO

select、poll、epoll簡介

epoll跟select都能提供多路I/O複用的解決方案;
select,pselect,poll,epoll本質上都是同步I/O;
因爲他們都需要在讀寫事件就緒後自己負責進行讀寫,也就是說這個讀寫過程是阻塞的

與多進程和多線程技術相比,I/O多路複用技術的最大優勢是系統開銷小,系統不必創建進程、線程,也不必維護這些進程/線程,從而大大減小了系統的開銷

select
select 函數監視的文件描述符分3類,分別是writefds、readfds和exceptfds;
調用後select函數會阻塞,直到有描述符就緒或者超時,函數返回;
當select函數返回後,可以通過遍歷fdset,來找到就緒的描述符。

select目前幾乎在所有的平臺上支持,其良好跨平臺支持也是它的一個優點;
select的一個缺點在於單個進程能夠監視的文件描述符的數量存在最大限制,在Linux上一般爲1024;
select本質上是通過設置或者檢查存放fd標誌位的數據結構來進行下一步處理;

缺點:
select最大的缺陷就是單個進程所打開的FD是有一定限制的,它由FD_SETSIZE設置,默認值是1024;
對socket進行掃描時是線性掃描,即採用輪詢的方法,效率較低;
需要維護一個用來存放大量fd的數據結構,這樣會使得用戶空間和內核空間在傳遞該結構時複製開銷大;

poll

poll本質上和select沒有區別,它將用戶傳入的數組拷貝到內核空間,然後查詢每個fd對應的設備狀態,如果設備就緒則在設備等待隊列中加入一項並繼續遍歷,如果遍歷完所有fd後沒有發現就緒設備,則掛起當前進程,直到設備就緒或者主動超時,被喚醒後它又要再次遍歷fd。這個過程經歷了多次無謂的遍歷。

它沒有最大連接數的限制,原因是它是基於鏈表來存儲的,但是同樣有缺點:
大量的fd的數組被整體複製於用戶態和內核地址空間之間,而不管這樣的複製是不是有意義;
poll還有一個特點是“水平觸發”,如果報告了fd後,沒有被處理,那麼下次poll時會再次報告該fd;

從上面看,select和poll都需要在返回後,通過遍歷文件描述符來獲取已經就緒的socket。事實上,同時連接的大量客戶端在一時刻可能只有很少的處於就緒狀態,因此隨着監視的描述符數量的增長,其效率也會線性下降。

epoll

相對於select和poll來說,epoll更加靈活,沒有描述符限制。epoll使用一個文件描述符管理多個描述符,將用戶關係的文件描述符的事件存放到內核的一個事件表中,這樣在用戶空間和內核空間的copy只需一次。

epoll支持水平觸發和邊緣觸發,最大的特點在於邊緣觸發,它只告訴進程哪些fd剛剛變爲就緒態,並且只會通知一次。還有一個特點是,epoll使用“事件”的就緒通知方式,通過epoll_ctl註冊fd,一旦該fd就緒,內核就會採用類似callback的回調機制來激活該fd,epoll_wait便可以收到通知;

優點:

沒有最大併發連接的限制,能打開的FD的上限遠大於1024(1G的內存上能監聽約10萬個端口);
效率提升,不是輪詢的方式,不會隨着FD數目的增加效率下降。只有活躍可用的FD纔會調用callback函數;即Epoll最大的優點就在於它只管你“活躍”的連接,而跟連接總數無關,因此在實際的網絡環境中,Epoll的效率就會遠遠高於select和poll。
內存拷貝,利用mmap()文件映射內存加速與內核空間的消息傳遞;即epoll使用mmap減少複製開銷

在select/poll中,進程只有在調用一定的方法後,內核纔對所有監視的文件描述符進行掃描,而epoll事先通過epoll_ctl()來註冊一個文件描述符,一旦基於某個文件描述符就緒時,內核會採用類似callback的回調機制,迅速激活這個文件描述符,當進程調用epoll_wait()時便得到通知。

參考:
https://www.cnblogs.com/dongguacai/p/5770287.html
https://www.jianshu.com/p/dfd940e7fca2

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章