先百度或者知乎,找到這篇文章 [1] IO 多路復用是什么意思?
文中提到:

那這樣子,在讀取socket1的數據時,如果其它socket有數據來,那么也要等到socket1讀取完了才能繼續讀取其它socket的數據吧。那不是也阻塞住了嗎?而且讀取到的數據也要開啟線程處理吧,那這和多線程IO有什么區別呢?

這里摘錄一些精彩回復
鏈接:https://www.zhihu.com/question/32163005/answer/55772739
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
select, poll, epoll 都是I/O多路復用的具體的實現,之所以有這三個鬼存在,其實是他們出現是有先后順序的。
I/O多路復用這個概念被提出來以后, select是第一個實現 (1983 左右在BSD里面實現的)。
select 被實現以后,很快就暴露出了很多問題。- select 會修改傳入的參數數組,這個對於一個需要調用很多次的函數,是非常不友好的。
- select 如果任何一個sock(I/O stream)出現了數據,select 僅僅會返回,但是並不會告訴你是那個sock上有數據,於是你只能自己一個一個的找,10幾個sock可能還好,要是幾萬的sock每次都找一遍,這個無謂的開銷就頗有海天盛筵的豪氣了。
- select 只能監視1024個鏈接, 這個跟草榴沒啥關系哦,linux 定義在頭文件中的,參見FD_SETSIZE。
- select 不是線程安全的,如果你把一個sock加入到select, 然后突然另外一個線程發現,尼瑪,這個sock不用,要收回。對不起,這個select 不支持的,如果你喪心病狂的竟然關掉這個sock, select的標准行為是。。呃。。不可預測的, 這個可是寫在文檔中的哦.
“If a file descriptor being monitored by select() is closed in another thread, the result is unspecified”
霸不霸氣
- poll 去掉了1024個鏈接的限制,於是要多少鏈接呢, 主人你開心就好。
- poll 從設計上來說,不再修改傳入數組,不過這個要看你的平台了,所以行走江湖,還是小心為妙。
其實拖14年那么久也不是效率問題, 而是那個時代的硬件實在太弱,一台服務器處理1千多個鏈接簡直就是神一樣的存在了,select很長段時間已經滿足需求。
但是poll仍然不是線程安全的, 這就意味着,不管服務器有多強悍,你也只能在一個線程里面處理一組I/O流。你當然可以那多進程來配合了,不過然后你就有了多進程的各種問題。
於是5年以后, 在2002, 大神 Davide Libenzi 實現了epoll.
epoll 可以說是I/O 多路復用最新的一個實現,epoll 修復了poll 和select絕大部分問題, 比如:- epoll 現在是線程安全的。
- epoll 現在不僅告訴你sock組里面數據,還會告訴你具體哪個sock有數據,你不用自己去找了。
鏈接:https://www.zhihu.com/question/32163005/answer/76577586
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
要弄清問題 先要知道問題的出現原因
原因:
由於進程的執行過程是線性的(也就是順序執行),當我們調用低速系統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有什么區別呢?
1.CPU本來就是線性的 不論什么都需要順序處理 並行只能是多核CPU
io多路復用本來就是用來解決對多個I/O監聽時,一個I/O阻塞影響其他I/O的問題,跟多線程沒關系.
3.跟多線程相比較,線程切換需要切換到內核進行線程切換,需要消耗時間和資源. 而I/O多路復用不需要切換線/進程,效率相對較高,特別是對高並發的應用nginx就是用I/O多路復用,故而性能極佳.但多線程編程邏輯和處理上比I/O多路復用簡單.而I/O多路復用處理起來較為復雜.
鏈接:https://www.zhihu.com/question/32163005/answer/55687802
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
