零拷貝:零拷貝技術可以減少資料拷貝和共享匯流排操作的次數,消除通訊資料在儲存器之間不必要的中間拷貝過程,有效地提高通訊效率,是設計高速介面通道、實現高速伺服器和路由器的關鍵技術之一。
sendfile
#include
ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count);
引數特別注意的是:in_fd必須是乙個支援mmap函式的檔案描述符,也就是說必須指向真實檔案,不能使socket描述符和管道。
out_fd必須是乙個socket描述符.
由此可見sendfile幾乎是專門為在網路上傳輸檔案而設計的。
out_fd:已經開啟了,用於寫操作的檔案描述符
in_fd:已經開啟了,用於讀操作的檔案描述符
offset:偏移量:表示sendfile函式從in_fd中的哪一偏移量開始讀取資料,如果是0表示從檔案的開始讀,否則從相應的偏移量讀取,如果是迴圈讀取的時候,下一次offset值應為sendfile函式返回值加上本次的offset的值。
count:是在兩個描述符之間拷貝的位元組數
返回值:
如果成功的拷貝,返回寫操作到out_fd的位元組數,錯誤返回-1,並相應的設定error資訊。
關於sendfile與read和write的比較
伺服器響應乙個http請求的步驟如下:
1.把磁碟檔案讀入核心緩衝區
2.從核心緩衝區讀到記憶體
3.處理(靜態資源不需要處理)
4.傳送到網絡卡的核心緩衝區(傳送快取)
5.網絡卡傳送資料
而sendfile系統呼叫,省略了2,3步,磁碟檔案被直接傳送到了網絡卡的記憶體緩衝區,減少了資料複製和核心態切換的開銷。
sendfile一直都在核心態進行
普通的read和write的傳統網路傳輸過程的步驟
read(file, tmp_buf, len);
write(socket, tmp_buf, len);
硬碟 >> kernel buffer >> user buffer >> kernel socket buffer >> 協議棧
一般的網路應用是通過讀硬碟資料,然後寫資料到socket來完成網路傳輸的。
底層實現如下:
1.系統呼叫read()產生乙個上下文切換:從使用者模式切換到核心模式,然後dma(直接記憶體訪問)執行拷貝,把檔案資料從硬碟讀到乙個核心緩衝區裡面去。
2.資料從核心緩衝區拷貝到使用者態緩衝區,然後系統呼叫read()返回,這時又產生乙個上下文切換:從核心狀態切換到使用者態。
3.系統呼叫write()產生乙個上下文切換:從使用者態切換到核心態,然後把步驟2中讀到使用者緩衝區的資料拷貝到核心態緩衝區(資料第二次拷貝到核心態緩衝區),不過這次是個不同的核心態緩衝區,這個緩衝區和socket相關聯。
4.系統呼叫write()返回,產生乙個上下文切換:從核心態切換到使用者態(第4次切換),然後dma從核心緩衝區拷貝資料到協議棧(第四次拷貝)。
上述4個步驟,4次上下文切換,4次拷貝,我們發現減少他的切換和拷貝次數,將有效提高效能。這也是sendfile提高效能的方法。
關於sendfile進行網路傳輸的過程
sendfile(socket, file, len);
硬碟 >> kernel buffer (快速拷貝到kernel socket buffer) >> 協議棧
1.系統呼叫sendfile()通過dma把硬碟資料拷貝到核心緩衝區,然後資料直接拷貝到另乙個與socket相關的核心緩衝區。(區別)這裡沒有使用者態和核心態之間的切換,在核心態中直接完成了從乙個緩衝區到另乙個緩衝區的拷貝。
2.dma把資料從核心緩衝區直接拷貝給協議棧,沒有切換,也不需要資料從使用者態拷貝到核心態,因為資料就在核心裡面。
由此比較,sendfile遠比read和write方式在進行資料拷貝時高效。
關於sendfile的應用**–**作用是把a檔案(和客戶端程式在同一目錄下)傳遞給伺服器端
服務端
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc,char* argv)
char buff[128] = ;
recv(c,buff,127,0);
printf("%s",buff);
}close(c);
return
0;}
客戶端
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc,char* argv)
printf("發出了%d個位元組\n",len);
}close(sockfd);
return
0;}
sendfile 實現零拷貝詳解
2013年11月18日 11 17 供稿中心 網際網路運營部 摘要 linux的sendfile 系統呼叫 伺服器響應乙個http請求的步驟如下 1 把磁碟檔案讀入核心緩衝區 2 從核心緩衝區讀到記憶體 3 處理 靜態資源不需處理 4 傳送到網絡卡的核心緩衝區 傳送快取 5 網絡卡傳送資料 資料從第...
sendfile「零拷貝」和mmap記憶體對映
在學習sendfille之前,我們先來了解一下瀏覽器訪問頁面時,後台伺服器的大致工作流程。下圖是從使用者訪問某個頁面到頁面的顯示這幾秒鐘的時間當中,在後台的整個工作過程。如上圖,黑色箭頭所示的過程,是傳統方式的資料傳輸 第一步 當使用者請求www.test.com index.html網頁時,ngi...
sendfile「零拷貝」和mmap記憶體對映
在學習sendfille之前,我們先來了解一下瀏覽器訪問頁面時,後台伺服器的大致工作流程。下圖是從使用者訪問某個頁面到頁面的顯示這幾秒鐘的時間當中,在後台的整個工作過程。如上圖,黑色箭頭所示的過程,是傳統方式的資料傳輸 第一步 當使用者請求www.test.com index.html網頁時,ngi...