天天看點

IO模式——同步(阻塞、非阻塞)、異步

為什麼IO模式很重要?因為現代的計算機和作業系統的架構決定了CPU是稀缺資源,大家都要來一起競争,而IO(特别是網絡相關的IO)的速度往往較慢。是以如何進行IO就有了多種模式,包括同步、異步、阻塞、非阻塞等等。

不少人把這幾個概念放到一起讨論,很多時候也難以區分。

這裡從根上剖析下該怎麼看待這幾個概念。

首先,異步和同步是相對的,而同步情況下又有阻塞和非阻塞之分。

異步很容易了解。當使用者程式需要進行IO的時候,發出IO請求,然後就立刻傳回,可以繼續做其它事情。

例如,從網絡收包,當包抵達後放到核心某個緩存區,并且從核心空間放置到程式需要的使用者空間後(一種是直接複制,比較費資源;一種是映射mmap),通知程式,程式之後就可以處理資料了。

這是最理想的模式,CPU幹活效率最高。

同步情況則是,當使用者程式需要進行IO的時候,發出IO請求,然後就等着資料到達後進行處理(首先将資料從核心空間複制到使用者空間,然後進行操作)。

具體怎麼等呢?一種就是阻塞在那裡,CPU就處理其它的程式去了;一種就是發現沒有資料就傳回一個錯誤,程式可以幹點别的事情(通常是不斷輪詢),過會還得自己主動回來看看資料OK了麼。

同步情況下顯然效率比較差,于是有了各種技術來改進它,一種就是IO多路複用(用一個專門的線程來負責IO),包括Linux上的select、poll和epoll。

select和poll類似,都是用一個核心優化線程來不斷輪詢IO,一旦有資料了使用者程式就可以利用系統調用将資料從核心空間複制到使用者空間,之後進行處理。這雖然提高了效率,但其實仍然是一種同步模式。

epoll則更進一步,采用了底層的notify機制和mmap,底層資料可用後通知IO線程,并利用mmap将資料直接映射到使用者空間。此時使用者程式可以直接對資料進行操作了。