Zero-Copysendfile浅析
Zero-Copy&sendfile淺析
標簽: buffersocket磁盤linuxlighttpdweb服務 2011-01-17 11:53 2923人閱讀 評論(0) 收藏 舉報 分類: 高性能服務器版權聲明:本文為博主原創文章,未經博主允許不得轉載。
一、典型IO調用的問題
一個典型的web服務器傳送靜態文件(如CSS,JS,圖片等)的過程如下:
read(file, tmp_buf, len);
write(socket, tmp_buf, len);
首先調用read將文件從磁盤讀取到tmp_buf,然后調用write將tmp_buf寫入到socket,在這過程中會出現四次數據 copy,過程如圖1所示
圖1
?
1。當調用read系統調用時,通過DMA(Direct Memory Access)將數據copy到內核模式
2。然后由CPU控制將內核模式數據copy到用戶模式下的 buffer中
3。read調用完成后,write調用首先將用戶模式下 buffer中的數據copy到內核模式下的socket buffer中
4。最后通過DMA copy將內核模式下的socket buffer中的數據copy到網卡設備中傳送。
從上面的過程可以看出,數據白白從內核模式到用戶模式走了一 圈,浪費了兩次copy,而這兩次copy都是CPU copy,即占用CPU資源。
?
二、Zero-Copy&Sendfile()
Linux 2.1版本內核引入了sendfile函數,用于將文件通過socket傳送。
sendfile(socket, file, len);
該函數通過一次系統調用完成了文件的傳送,減少了原來 read/write方式的模式切換。此外更是減少了數據的copy,sendfile的詳細過程圖2所示:
圖2
通過sendfile傳送文件只需要一次系統調用,當調用 sendfile時:
1。首先通過DMA copy將數據從磁盤讀取到kernel buffer中
2。然后通過CPU copy將數據從kernel buffer copy到sokcet buffer中
3。最終通過DMA copy將socket buffer中數據copy到網卡buffer中發送
sendfile與read/write方式相比,少了 一次模式切換一次CPU copy。但是從上述過程中也可以發現從kernel buffer中將數據copy到socket buffer是沒必要的。
為此,Linux2.4內核對sendfile做了改進,如圖3所示
圖3
改進后的處理過程如下:
1。DMA copy將磁盤數據copy到kernel buffer中
2。向socket buffer中追加當前要發送的數據在kernel buffer中的位置和偏移量
3。DMA gather copy根據socket buffer中的位置和偏移量直接將kernel buffer中的數據copy到網卡上。
經過上述過程,數據只經過了2次copy就從磁盤傳送出去了。
(可能有人要糾結“不是說Zero-Copy么?怎么還有兩次copy啊”,事實上這個Zero copy是針對內核來講的,數據在內核模式下是Zero-copy的。話說回來,文件本身在瓷盤上要真是完全Zero-copy就能傳送,那才見鬼了 呢)。
當前許多高性能http server都引入了sendfile機制,如nginx,lighttpd等。
三、Java NIO中的transferTo()
Java NIO中
FileChannel.transferTo(long position, long count, WriteableByteChannel target)
方法將當前通道中的數據傳送到目標通道target中,在支持Zero-Copy的linux系統中,transferTo()的實現依賴于 sendfile()調用。
?
四、參考文檔
《Zero Copy I: User-Mode Perspective》http://www.linuxjournal.com/article/6345?page=0,0
《Efficient data transfer through zero copy》http://www.ibm.com/developerworks/linux/library/j-zerocopy
《The C10K problem》http://www.kegel.com/c10k.html
總結
以上是生活随笔為你收集整理的Zero-Copysendfile浅析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Adobe illustrator 排版
- 下一篇: MEGA | 多序列比对及系统发育树的构