近期在招聘中,發現不少人對bio、nio、aio等理解非常模糊,認為有必要寫文章來糾正下非常多人的誤解。
在談這些之前,非常有必要先介紹下unix 5種io模型:
堵塞:
堵塞是最經常使用的io模型,預設情況下全部的檔案操作都是堵塞的。以套接字程式設計為例。在程序空間中呼叫recvfrom。其系統呼叫直到資料報文到達且被複製到應用程式程序的快取區(或者錯誤發生)後才返回,期間一直在等待。
程序在從呼叫recvfrom開始到它返回的整段時間內是被堵塞的。有一張非常經典的圖:
非堵塞:
呼叫recvfrom從應用層到核心的過程中,假設該緩衝區沒有資料的話,則直接返回乙個ewouldblock的錯誤,通常會輪詢的進行檢查狀態,看核心空間有沒有資料來。
直到有資料,最後完畢拷貝。
例如以下圖:
io多路復用:
linux系統提供的select/poll/epoll,程序將乙個或者多個fd(檔案描寫敘述符)傳遞給乙個或者多個poll/select系統呼叫,堵塞在select。
select和poll能夠幫助偵聽非常多的fd是否準備就緒。可是,select和poll是順序掃瞄去檢查fd的就緒狀態。效率比較低,並且支援的fd數量有限(沒記錯的話,預設好像是1024還是2048。詳細記不清)。而epoll是通過事件驅動的方式,當有fd準備就緒的時候,馬上**函式rollback。如圖:
談到epoll,不得不提乙個經典的問題。apache和nginx的對照。為什麼nginx比apache效率高非常多,這就是根本的原因。
訊號驅動:
這樣的模型在實際應用的非常少,這裡不做過多介紹,能夠看圖:
非同步:
告知核心啟動某個操作。並讓核心在整個操作完畢後(包含將資料從核心空間複製到自己的緩衝區)通知。非同步io的主要特點是完畢操作後主動通知。如圖:
好,上面的可能有點抽象。以下用通俗點的語言來總結一下堵塞,非堵塞。同步,非同步
堵塞,非堵塞:程序/執行緒要訪問的資料是否就緒,程序/執行緒是否須要等待;
同步,非同步:訪問資料的方式,同步須要主動讀寫資料。在讀寫資料的過程中還是會堵塞;
非同步僅僅須要i/o操作完畢的通知。並不主動讀寫資料,由作業系統核心完畢資料的讀寫。
再舉個網上流傳的,非常easy理解的樣例:
老張愛喝茶。廢話不說。煮開水。
出場人物:老張。水壺兩把(普通水壺。簡稱水壺;會響的水壺。簡稱響水壺)。
1 老張把水壺放到火上,立等水開。(同步堵塞)老張認為自己有點傻
2 老張把水壺放到火上,去客廳看電視,時不時去廚房看看水開沒有。(同步非堵塞)
老張還是認為自己有點傻,於是變高階了。買了把會響笛的那種水壺。
水開之後,能大聲發出嘀~~~~的噪音。
3 老張把響水壺放到火上。立等水開。(非同步堵塞)老張認為這樣傻等意義不大
4 老張把響水壺放到火上,去客廳看電視,水壺響之前不再去看它了,響了再去拿壺。(非同步非堵塞)老張認為自己聰明了。
所謂同步非同步。僅僅是對於水壺而言。普通水壺,同步;響水壺。非同步。儘管都能幹活,但響水壺能夠在自己完工之後,提示老張水開了。
這是普通水壺所不能及的。
同步僅僅能讓呼叫者去輪詢自己(情況2中),造成老張效率的低下。
所謂堵塞非堵塞,僅僅對於老張而言。
立等的老張。
堵塞。看電視的老張。非堵塞。
情況1和情況3中老張就是堵塞的。媳婦喊他都不知道。
儘管3中響水壺是非同步的。可對於立等的老張沒有太大的意義。所以一般非同步是配合非堵塞使用的,這樣才幹發揮非同步的效用。
IO模式 同步(堵塞 非堵塞) 非同步
為什麼io模式非常重要?由於現代的計算機和作業系統的架構決定了cpu是稀缺資源,大家都要來一起競爭。而io 特別是網路相關的io 的速度往往較慢。所以怎樣進行io就有了多種模式,包含同步 非同步 堵塞 非堵塞等等。不少人把這幾個概念放到一起討論,非常多時候也難以區分。這裡從根上剖析下該怎麼看待這幾個...
php socket 同步非同步堵塞非堵塞的區別
php socket 同步非同步堵塞非堵塞的區別 從accept接受資料開始 同步就是 服務端從客戶端接受完資料 處理 然後傳送給客戶端了 然後再開始接收新的客戶端發來的資料 非同步就是 服務端從客戶端接受完資料 就可以再次繼續接收 非同步處理資料 堵塞就是 服務端堵塞執行緒狀態接收資料 read ...
理解非同步 同步 並行 併發 堵塞 非堵塞
一 同步vs非同步 同步和非同步我們經常見的,同步 執行方法是有時間順序的,例如我們執行乙個同步方法,必須等這個方法執行結束才能執行下一步操作,非同步 沒有時間順序,不需要等這個方法執行完,我們就可以執行下一步操作。二 並行vs併發 併發我們經常聽見,但是並行很少聽見吧,並行 就是一起執行,同時進行...