天天看點

sendfile學習

參考

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

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

Sendfile(2)在這個時代背景下于2003年前後被加入Linux Kernel,陸續在各大UNIX、Linux、Solaris平台上獲得了支援。這個系統核心調用本身被設計出來是用來從磁盤到TCP協定棧拷貝資料用的,但也我們也是可以把它用來做兩個檔案之間的資料拷貝。

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

in_fd 被打開是等待讀資料的fd.

out_fd 被打開是等待寫資料的fd.

Offset 是在正式開始讀取資料之前應該向前偏移的byte數.

count 是需要在兩個fd之間“搬移”的資料的byte數.

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

out_fd必須是一個socket描述符。

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

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

調用read(2)函數,檔案資料被copy到核心緩沖區

read(2)函數傳回,檔案資料從核心緩沖區copy到使用者緩沖區

write(2)函數調用,将檔案資料從使用者緩沖區copy到核心與socket相關的緩沖區。

資料從socket緩沖區copy到相關協定引擎。

sendfile學習

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

不必要的記憶體拷貝。

系統調用帶來的額外的使用者态/核心态上下文切換(Context Switch)。

sendfile學習

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

sendfile學習

繼續閱讀