零拷貝
零拷貝是指計算機執行IO操作時,CPU不需要將數據從一個存儲區域復制到另一個存儲區域,從而可以減少上下文切換以及CPU的拷貝時間。它是一種I/O操作優化技術。
傳統 IO 的執行流程
傳統的IO流程,包括read和write的過程。
- read:把數據從磁盤讀取到內核緩沖區,再拷貝到用戶緩沖區
- write:先把數據寫入到socket緩沖區,最后寫入網卡設備。
文件下載舉例:
1、用戶應用進程調用read函數,向操作系統發起IO調用,上下文從用戶態轉為內核態(切換1)
2、DMA控制器把數據從磁盤中,讀取到內核緩沖區。
3、CPU把內核緩沖區數據,拷貝到用戶應用緩沖區,上下文從內核態轉為用戶態(切換2),read函數返回
4、用戶應用進程通過write函數,發起IO調用,上下文從用戶態轉為內核態(切換3)
5、CPU將用戶緩沖區中的數據,拷貝到socket緩沖區
6、DMA控制器把數據從socket緩沖區,拷貝到網卡設備,上下文從內核態切換回用戶態(切換4),write函數返回
傳統IO的讀寫流程,包括了4次上下文切換(4次用戶態和內核態的切換),4次數據拷貝(兩次CPU拷貝以及兩次的DMA拷貝)。
零拷貝實現方式:
零拷貝並不是沒有拷貝數據,而是減少用戶態/內核態的切換次數以及CPU拷貝的次數。零拷貝一般有這三種實現方式:
• mmap+write
• sendfile
• 帶有DMA收集拷貝功能的sendfile
mmap+write
mmap就是用了虛擬內存這個特點,它將內核中的讀緩沖區與用戶空間的緩沖區進行映射,以減少數據拷貝次數!
1、用戶進程通過mmap方法向操作系統內核發起IO調用,上下文從用戶態切換為內核態。
2、CPU利用DMA控制器,把數據從硬盤中拷貝到內核緩沖區。
3、上下文從內核態切換回用戶態,mmap方法返回。
4、用戶進程通過write方法向操作系統內核發起IO調用,上下文從用戶態切換為內核態。
5、CPU將內核緩沖區的數據拷貝到的socket緩沖區。
6、CPU利用DMA控制器,把數據從socket緩沖區拷貝到網卡,上下文從內核態切換回用戶態,write調用返回。
mmap+write實現的零拷貝,I/O發生了4次用戶空間與內核空間的上下文切換,以及3次數據拷貝(包括了2次DMA拷貝和1次CPU拷貝)。
sendfile
sendfile表示在兩個文件描述符之間傳輸數據,它是在操作系統內核中操作的,避免了數據從內核緩沖區和用戶緩沖區之間的拷貝操作。
1、用戶進程發起sendfile系統調用,上下文(切換1)從用戶態轉向內核態
2、DMA控制器,把數據從硬盤中拷貝到內核緩沖區。
3、CPU將讀緩沖區中數據拷貝到socket緩沖區
4、DMA控制器,異步把數據從socket緩沖區拷貝到網卡,
5、上下文(切換2)從內核態切換回用戶態,sendfile調用返回。
sendfile實現的零拷貝,I/O發生了2次用戶空間與內核空間的上下文切換,以及3次數據拷貝。其中3次數據拷貝中,包括了2次DMA拷貝和1次CPU拷貝。
帶有DMA收集拷貝功能的sendfile
linux 2.4版本之后,對sendfile做了優化升級,引入SG-DMA技術,其實就是對DMA拷貝加入了scatter/gather操作,它可以直接從內核空間緩沖區中將數據讀取到網卡。使用這個特點搞零拷貝,即還可以多省去一次CPU拷貝。
1、用戶進程發起sendfile系統調用,上下文(切換1)從用戶態轉向內核態
2、DMA控制器,把數據從硬盤中拷貝到內核緩沖區。
3、CPU把內核緩沖區中的文件描述符信息(包括內核緩沖區的內存地址和偏移量)發送到socket緩沖區
4、DMA控制器根據文件描述符信息,直接把數據從內核緩沖區拷貝到網卡
5、上下文(切換2)從內核態切換回用戶態,sendfile調用返回。
可以發現,sendfile+DMA scatter/gather實現的零拷貝,I/O發生了2次用戶空間與內核空間的上下文切換,以及2次數據拷貝。其中2次數據拷貝都是包DMA拷貝。這就是真正的 零拷貝(Zero-copy) 技術,全程都沒有通過CPU來搬運數據,所有的數據都是通過DMA來進行傳輸的。