sendfile原理,實現檔案傳輸效能的提升
阿新 • • 發佈:2019-02-01
在apache,nginx,lighttpd等web伺服器當中,都有一項sendfile相關的配置,在一些網上的資料都有談到sendfile會提升檔案傳輸效能,那sendfile到底是什麼呢?它的原理又是如何呢?
在傳統的檔案傳輸裡面(read/write方式),在實現上其實是比較複雜的,需要經過多次上下文的切換,我們看一下如下兩行程式碼:
Java程式碼
以上兩行程式碼是傳統的read/write方式進行檔案到socket的傳輸。
當需要對一個檔案進行傳輸的時候,其具體流程細節如下:
1、呼叫read函式,檔案資料被copy到核心緩衝區
2、read函式返回,檔案資料從核心緩衝區copy到使用者緩衝區
3、write函式呼叫,將檔案資料從使用者緩衝區copy到核心與socket相關的緩衝區。
4、資料從socket緩衝區copy到相關協議引擎。
以上細節是傳統read/write方式進行網路檔案傳輸的方式,我們可以看到,在這個過程當中,檔案資料實際上是經過了四次copy操作:
硬碟—>核心buf—>使用者buf—>socket相關緩衝區—>協議引擎
而sendfile系統呼叫則提供了一種減少以上多次copy,提升檔案傳輸效能的方法。Sendfile系統呼叫是在2.1版本核心時引進的:
Java程式碼
執行流程如下:
1、sendfile系統呼叫,檔案資料被copy至核心緩衝區
2、再從核心緩衝區copy至核心中socket相關的緩衝區
3、最後再socket相關的緩衝區copy到協議引擎
相較傳統read/write方式,2.1版本核心引進的sendfile已經減少了核心緩衝區到user緩衝區,再由user緩衝區到socket相關緩衝區的檔案copy,而在核心版本2.4之後,檔案描述符結果被改變,sendfile實現了更簡單的方式,系統呼叫方式仍然一樣,細節與2.1版本的不同之處在於,當檔案資料被複制到核心緩衝區時,不再將所有資料copy到socket相關的緩衝區,而是僅僅將記錄資料位置和長度相關的資料儲存到socket相關的快取,而實際資料將由DMA模組直接傳送到協議引擎,再次減少了一次copy操作。
以上描述雖然簡單,但實際情況會更加複雜,本文只希望以簡單的方式大致上講解sendfile的原理,並不奢望通過本文能夠闡述出所有的細節,我也沒這水平,希望此文對各位朋友有所幫助。
在傳統的檔案傳輸裡面(read/write方式),在實現上其實是比較複雜的,需要經過多次上下文的切換,我們看一下如下兩行程式碼:
Java程式碼
- read(file, tmp_buf, len);
- write(socket, tmp_buf, len);
以上兩行程式碼是傳統的read/write方式進行檔案到socket的傳輸。
當需要對一個檔案進行傳輸的時候,其具體流程細節如下:
1、呼叫read函式,檔案資料被copy到核心緩衝區
2、read函式返回,檔案資料從核心緩衝區copy到使用者緩衝區
3、write函式呼叫,將檔案資料從使用者緩衝區copy到核心與socket相關的緩衝區。
4、資料從socket緩衝區copy到相關協議引擎。
以上細節是傳統read/write方式進行網路檔案傳輸的方式,我們可以看到,在這個過程當中,檔案資料實際上是經過了四次copy操作:
硬碟—>核心buf—>使用者buf—>socket相關緩衝區—>協議引擎
而sendfile系統呼叫則提供了一種減少以上多次copy,提升檔案傳輸效能的方法。Sendfile系統呼叫是在2.1版本核心時引進的:
Java程式碼
- sendfile(socket, file, len);
執行流程如下:
1、sendfile系統呼叫,檔案資料被copy至核心緩衝區
2、再從核心緩衝區copy至核心中socket相關的緩衝區
3、最後再socket相關的緩衝區copy到協議引擎
相較傳統read/write方式,2.1版本核心引進的sendfile已經減少了核心緩衝區到user緩衝區,再由user緩衝區到socket相關緩衝區的檔案copy,而在核心版本2.4之後,檔案描述符結果被改變,sendfile實現了更簡單的方式,系統呼叫方式仍然一樣,細節與2.1版本的不同之處在於,當檔案資料被複制到核心緩衝區時,不再將所有資料copy到socket相關的緩衝區,而是僅僅將記錄資料位置和長度相關的資料儲存到socket相關的快取,而實際資料將由DMA模組直接傳送到協議引擎,再次減少了一次copy操作。
以上描述雖然簡單,但實際情況會更加複雜,本文只希望以簡單的方式大致上講解sendfile的原理,並不奢望通過本文能夠闡述出所有的細節,我也沒這水平,希望此文對各位朋友有所幫助。
參考自:http://www.linuxjournal.com/article/6345
-----------------------------------------------------------------------------------------------------------------------------------------------------------
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
out_fd
a file descriptor, open for writing, for the data to be written
in_fd
a file descriptor, open for reading, for the data to be read
offset
the offset in the input file to start transfer (e.g. a value of 0 indicates the beginning of the file). This is passed into the function and updated when the function returns.
count
the number of bytes to be transferred
|