sendfile學習


參考

https://zhuanlan.zhihu.com/p/20768200?refer=auxten

 

而成本很多時候的體現就是對計算資源的消耗,其中最重要的一個資源就是CPU資源。

 

Sendfile(2)在這個時代背景下於2003年前后被加入Linux Kernel,陸續在各大UNIX、Linux、Solaris平台上獲得了支持。這個系統內核調用本身被設計出來是用來從磁盤到TCP協議棧拷貝數據用的,但也我們也是可以把它用來做兩個文件之間的數據拷貝。

在Linux Kernel 2.6版本中,這個系統調用的原型是這樣的:

ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count) 
  • in_fd 被打開是等待讀數據的fd.
  • out_fd 被打開是等待寫數據的fd.
  • Offset 是在正式開始讀取數據之前應該向前偏移的byte數.
  • count 是需要在兩個fd之間“搬移”的數據的byte數.

參數特別注意的是:in_fd必須是一個支持mmap函數的文件描述符,也就是說必須指向真實文件,不能使socket描述符和管道。

out_fd必須是一個socket描述符。

由此可見sendfile幾乎是專門為在網絡上傳輸文件而設計的。


在sendfile(2)出現之前,我們想要把一個文件發送到socket上需要進行如下幾個步驟:

  1. 調用read(2)函數,文件數據被copy到內核緩沖區
  2. read(2)函數返回,文件數據從內核緩沖區copy到用戶緩沖區
  3. write(2)函數調用,將文件數據從用戶緩沖區copy到內核與socket相關的緩沖區。
  4. 數據從socket緩沖區copy到相關協議引擎。

 

 

相比sendfile(2),“Read & Write”方式帶來的性能損耗主要有兩點:

  1. 不必要的內存拷貝。
  2. 系統調用帶來的額外的用戶態/內核態上下文切換(Context Switch)。

 

 

而我們知道,上下文切換涉及到非常多的CPU、內存堆棧的操作,會讓分支預測失敗率大增,所以頻繁的上線文切換是高性能編程的大忌。類UNIX操作系統里都有一個系統命令vmstat可以展示當前系統的“Context Switch”的量(--system--下的cs列):

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM