先來說一下什么是IO復用?
IO復用解決的就是並發行的問題,比如多個用戶並發訪問一個WEB網站,對於服務端后台而言就會產生多個請求,處理多個請求對於中間件就會產生多個IO流對於系統的讀寫。那么對於IO流請求操作系統內核有並行處理和串行處理的概念,串行處理的方式是一個個處理,前面的發生阻塞,就沒辦法完成后面的請求。這個時候我們必須考慮並行的方式完成整個IO流的請求來實現最大的並發和吞吐,這時候就是用到IO復用技術。IO復用就是讓一個Socket來作為復用完成整個IO流的請求。當然實現整個IO流的請求多線程的方式就是其中一種。
***下面是一些舉例,讓你更清楚的了解什么是IO多路復用***
舉例:在教室里面有一個老師同時給學生出一道題目,檢查每個學生做的是否正確,這時候老師可以選擇一個一個學生的去問學生是否做完。如果A學生沒做完,那么再問B學生,B學生沒做完再問C學生,挨個問下去,如果發現問道某一個學生,某一個學生說做完的時候,這時候再給當下學生解答。那么這時候會發現,如果一個學生發生了阻塞,阻塞在一個學生下,其他學生就會耽誤了,這時候對整個課堂效率就底下。這就是串行請求類處理。
那么多線程呢?
再舉例:也是這個場景,給學生出題讓學生解答。這個老師學會了分身術,每個老師對每個學生進行監聽,看學生是否答題完並作出解答,這樣效率就高了。這就是多線程進行IO流處理,那么多線程IO流就會產生一定的消耗,資源問題的存在。
什么是IO多路復用呢?
再再舉例:同樣也是答題場景,其實就是改為了由學生來主動跟老師匯報,比如學生B答完了,這時候老師跟B進行解答,因為B學習效率高,其他學生還在做題,這時候給學生B解答完后,老師再給第二個學生解答,這時候學生主動匯報,效率就高了。這種方式就是IO多路復用的方式。特點:學生主動匯報。
對於操作系統而言,IO多路復用就是要完成操作系統IO的請求。對於IO文件的請求,當一個IO流要進行文件處理的時候,要獲取一組文件的描述符,當文件描述符還沒有就緒時,那么它就在等待,直到描述符一旦就緒,馬上上報系統通知的機制,告訴應用程序我准備就緒,你可以來操作了。這就是IO多路復用的方式。
這種機制處理起來就很高效,多路復用就是在一個線程里,交替並發的完成。復用的就是一個線程。
------------------------下面來看一下知乎帖子幾個前輩給出的比較粗俗易懂的解答------------------------
李遙:
你有N個不知道什么時候來水的水龍頭需要接水,你根據某種信號一會兒擰這個龍頭,一會兒擰那個龍頭把水都接了就是多路復用(一個線程)。使用殘像拳在每個水龍頭前派一個你的分身蹲守就是Threaded IO。其實后者也沒啥不好,因為未來的內核會消除上下文切換的軟硬件性能損耗。
Leslie:
要弄清問題先要知道問題的出現原因
原因:
由於進程的執行過程是線性的(也就是順序執行),當我們調用低速系統I/O(read,write,accept等等),進程可能阻塞,此時進程就阻塞在這個調用上,不能執行其他操作.阻塞很正常. 接下來考慮這么一個問題: 一個服務器進程和一個客戶端進程通信,服務器端read(sockfd1,bud,bufsize),此時客戶端進程沒有發送數據,那么read(阻塞調用)將阻塞直到客戶端調用write(sockfd,but,size) 發來數據. 在一個客戶和服務器通信時這沒什么問題,當多個客戶與服務器通信時,若服務器阻塞於其中一個客戶sockfd1,當另一個 客戶的數據到達套接字sockfd2時,服務器不能處理,仍然阻塞在read(sockfd1,...)上;此時問題就出現了,不能及時處理另一個客戶的服務,咋么辦?I/O多路復用來解決!
I/O多路復用:
繼續上面的問題,有多個客戶連接, sockfd1,sockfd2,sockfd3..sockfdn 同時監聽這n個客戶,當其中有一個發來消息 時就從select的阻塞中返回,然后就調用read讀取收到消息的sockfd,然后又循環回select 阻塞;這樣就不會因為阻塞在其中一個上而不能處理另一個客戶的消息
Q:
那這樣子,在讀取socket1的數據時,如果其它socket有數據來,那么也要等到socket1讀取完了才能繼續讀取其它socket的數據吧。那不是也阻塞住了嗎?而且讀取到的數據也要開啟線程處理吧,那這和多線程IO有什么區別呢?
A:
1.CPU本來就是線性的不論什么都需要順序處理並行只能是多核CPUhttp:
2.io多路復用本來就是用來解決對多個I/O監聽時,一個I/O阻塞影響其他I/O的問題,跟多線程沒關系.
3.跟多線程相比較,線程切換需要切換到內核進行線程切換,需要消耗時間和資源. 而I/O多路復用不需要切換線/進程,效率相對較高,特別是對高並發的應用nginx就是用I/O多路復用,故而性能極佳.但多線程編程邏輯和處理上比I/O多路復用簡單.而I/O多路復用處理起來較為復雜.
某匿名用戶:
這些名詞比較繞口,理解涵義就好。一個epoll場景:一個酒吧服務員(一個線程),前面趴了一群醉漢,突然一個吼一聲“倒酒”(事件),你小跑過去給他倒一杯,然后隨他去吧,突然又一個要倒酒,你又過去倒上,就這樣一個服務員服務好多人,有時沒人喝酒,服務員處於空閑狀態,可以干點別的玩玩手機。至於epoll與select,poll的區別在於后兩者的場景中醉漢不說話,你要挨個問要不要酒,沒時間玩手機了。io多路復用大概就是指這幾個醉漢共用一個服務員。
某匿名用戶:
1 人贊同了該回答
IO模式一般分為同步IO和異步IO. 同步IO會阻塞進程, 異步IO不會阻塞進程. 目前linux上大部分用的是同步IO, 異步IO在linux上目前還不成熟, 不過windows的iocp算是真正的異步IO。
同步IO又分為阻塞IO, 非阻塞IO, IO多路復用. What? 同步IO明明會阻塞進程,為什么也包括非阻塞IO? 因為非阻塞IO雖然在請求數據時不阻塞, 但真正數據來臨時,也就是內核數據拷貝到用戶數據時, 此時進程是阻塞的.
那么這些IO模式的區別分別是什么? 接下來舉個小例子來說明. 假設你現在去女生宿舍樓找自己的女神, 但是你只知道女神的手機號,並不知道女神的具體房間
先說同步IO的情況,
1. 阻塞IO, 給女神發一條短信, 說我來找你了, 然后就默默的一直等着女神下樓, 這個期間除了等待你不會做其他事情, 屬於備胎做法.
2. 非阻塞IO, 給女神發短信, 如果不回, 接着再發, 一直發到女神下樓, 這個期間你除了發短信等待不會做其他事情, 屬於專一做法.
3. IO多路復用,是找一個宿管大媽來幫你監視下樓的女生, 這個期間你可以些其他的事情. 例如可以順便看看其他妹子,玩玩王者榮耀, 上個廁所等等。IO復用又包括 select, poll, epoll 模式. 那么它們的區別是什么?
3.1 select大媽每一個女生下樓, select大媽都不知道這個是不是你的女神, 她需要一個一個詢問, 並且select大媽能力還有限, 最多一次幫你監視1024個妹子
3.2 poll大媽不限制盯着女生的數量, 只要是經過宿舍樓門口的女生, 都會幫你去問是不是你女神
3.3 epoll大媽不限制盯着女生的數量, 並且也不需要一個一個去問. 那么如何做呢? epoll大媽會為每個進宿舍樓的女生臉上貼上一個大字條,上面寫上女生自己的名字, 只要女生下樓了, epoll大媽就知道這個是不是你女神了, 然后大媽再通知你.
上面這些同步IO有一個共同點就是, 當女神走出宿舍門口的時候, 你已經站在宿舍門口等着女神的, 此時你屬於阻塞狀態
接下來是異步IO的情況
你告訴女神我來了, 然后你就去王者榮耀了, 一直到女神下樓了, 發現找不見你了, 女神再給你打電話通知你, 說我下樓了, 你在哪呢? 這時候你才來到宿舍門口. 此時屬於逆襲做法。
總結:
有多個客戶連接,1、2、3、4、5、N同時監聽這M個客戶,當其中有一個發來消息時就從阻塞中返回,然后就進行 請求處理,然后又循環回阻塞;這樣就不會因為阻塞在其中一個上而不能處理另一個客戶的消息
具體帖子地址:https://www.zhihu.com/question/32163005