IO會一直占用CPU嗎?
這是一個很好的關於並發/並行系統的問題。簡單回答就是:IO所需要的CPU資源非常少。大部分工作是分派給DMA(Direct Memory Access)直接內存存取完成的。先不談傳統的5大IO模型,先說說並發(Concurrencey)。一個非常不嚴謹的解釋就是同時做A和B兩件事。先做一會兒進程A,然后上下文切換,再做一會兒B。過一會兒在切回來繼續做A。因此給我們造成一個假象,我們同時在做A和B兩件事。這就是著名的進程模型。這看上去很炫酷,但實際上並沒有任何卵用。因為A,B兩件事你都得做完不是?不論你是做完A再做B還是來回切換,花得時間應該是一樣的。甚至還要更多,因為還要考慮到上下文切換的開銷。
如果計算機內部不止CPU一個部件在工作呢?如果A這件事CPU可以分派給其他部件幫它完成呢?情況是不是就完全不一樣了?
系統IO正好是這樣一個完美的例子。對於磁盤IO,真實發生的場景可能是這樣的:

當然我們也可以到網上下載蒼老師的作品,這就是網絡IO。但情況基本是一樣的,CPU童鞋在等小電影的過程中,打了一局擼啊擼。所以,正因為這樣派發任務,通訊,等待的過程,並發系統才彰顯出它的意義。當然實際過程可能比這個復雜一萬倍。比如CPU是不會直接和硬盤對話的,他們之間有個中間人,叫DMA(Direct Memory Access)芯片

這個過程,對應下圖(圖源:《UNIX網絡編程》),看到application這一列時間線了嗎?aio_read操作之后,都是空白,CPU就不管了,可以做其他事去了。

假設原先讀取文件CPU需要傻等50納秒。現在盡管兩次上下文切換要各消耗5納秒。CPU還是賺了40納秒時間片。一看上面這張圖就知道,剛才講的是傳統5大IO模型中的“異步IO”的大致過程。計算機硬件上使用DMA來訪問磁盤等IO,也就是請求發出后,CPU就不再管了,直到DMA處理器完成任務,再通過中斷告訴CPU完成了。所以,單獨的一個IO時間,對CPU的占用是很少的,阻塞了就更不會占用CPU了,單線程環境下會導致程序都不繼續運行了,在多線程環境下,CPU會把時間交給其它線程和進程了。
那么問題來了,這個IO操作會阻塞多久?CPU什么時候會切回到原線程並繼續執行?
這里涉及到上文提到的IO通信模型。雖然IO不會占用大量的CPU時間,但是非常頻繁的IO還是會非常浪費CPU時間的,所以面對大量IO的任務,有時候是需要算法來合並IO,或者通過cache來緩解IO壓力的,使用良好的通信模型也會大大提高我們的代碼的執行效率。
