原文來自知乎:https://www.zhihu.com/question/27734728
這是一個很好的關於並發/並行系統的問題。簡單回答就是: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,真實發生的場景可能是這樣的:
CPU說:硬盤兄幫我把我要看的小電影拷貝一份到主存,謝謝,親。
硬盤說:好的!我考完了叫你。
CPU說:么么噠!那我打游戲去啦!
...
CPU打擼啊擼 (100納秒過去了)
...
硬盤說:小C我考完了。
CPU說:蒼老師我來啦!
當然我們也可以到網上下載蒼老師的作品,這就是網絡IO。但情況基本是一樣的,CPU童鞋在等小電影的過程中,打了一局擼啊擼。
所以,正因為這樣派發任務,通訊,等待的過程,並發系統才彰顯出它的意義。當然實際過程可能比這個復雜一萬倍。比如CPU是不會直接和硬盤對話的,他們之間有個中間人,叫DMA(Direct Memory Access)芯片
CPU計算文件地址 ——> 委派DMA讀取文件 ——> DMA接管總線 ——> CPU的A進程阻塞,掛起——> CPU切換到B進程 ——>
DMA讀完文件后通知CPU(一個中斷異常)——> CPU切換回A進程操作文件
這個過程,對應下圖(圖源:《UNIX網絡編程》),看到application這一列時間線了嗎?aio_read操作之后,都是空白,CPU就不管了,可以做其他事去了。
假設原先讀取文件CPU需要傻等50納秒。現在盡管兩次上下文切換要各消耗5納秒。CPU還是賺了40納秒時間片。一看上面這張圖就知道,剛才講的是傳統5大IO模型中的“異步IO”的大致過程。想進一步了解,推薦直接讀《UNIX網絡編程》第一冊套接字,經典哦!
計算機硬件上使用DMA來訪問磁盤等IO,也就是請求發出后,CPU就不再管了,直到DMA處理器完成任務,再通過中斷告訴CPU完成了。所以,單獨的一個IO時間,對CPU的占用是很少的,阻塞了就更不會占用CPU了,因為程序都不繼續運行了,CPU時間交給其它線程和進程了。雖然IO不會占用大量的CPU時間,但是非常頻繁的IO還是會非常浪費CPU時間的,所以面對大量IO的任務,有時候是需要算法來合並IO,或者通過cache來緩解IO壓力的。
你知道IO的五種方式嗎?
程序直接控制
中斷
DMA
外圍處理機
通道