最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

一文讀懂零拷貝技術(shù)|splice原理與實(shí)現(xiàn)

2022-10-15 16:37 作者:補(bǔ)給站Linux內(nèi)核  | 我要投稿

splice 原理重溫

《splice使用》一文中介紹了 的原理和使用,現(xiàn)在我們來分析一下 的代碼實(shí)現(xiàn)。splice``splice

我們先來回顧一下 ?的原理:splice



如上圖所示,使用 拷貝數(shù)據(jù)時(shí),需要通過管道作為中轉(zhuǎn)。首先將 綁定到 的寫端,然后通過 的讀端讀取到 的數(shù)據(jù),并且拷貝到 緩沖區(qū)中。splice``splice``頁緩存``管道``管道``頁緩存``socket

管道的實(shí)現(xiàn)可以參考:《圖解 |Linux進(jìn)程通信 - 管道實(shí)現(xiàn)

我們在《圖解 |Linux進(jìn)程通信 - 管道實(shí)現(xiàn)》一文中介紹過,管道有個(gè) ,這個(gè) 需要綁定真實(shí)的物理內(nèi)存頁。而 splice 就是將管道的 綁定到文件的 ,如下圖所示:環(huán)形緩沖區(qū)``環(huán)形緩沖區(qū)``環(huán)形緩沖區(qū)``頁緩存



通過將文件頁緩存綁定到管道的環(huán)形緩沖區(qū)后,就可以通過管道的讀端讀取文件頁緩存的數(shù)據(jù)。


【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個(gè)人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦!?。。ê曨l教程、電子書、實(shí)戰(zhàn)項(xiàng)目及代碼)??

splice 代碼實(shí)現(xiàn)

《splice使用》一文中介紹過 的使用過程,要將文件內(nèi)容發(fā)送到客戶端連接的步驟如下:splice

  1. 首先,使用 ?系統(tǒng)調(diào)用將文件的內(nèi)容與管道綁定。splice()

  2. 然后,使用 系統(tǒng)調(diào)用將管道的數(shù)據(jù)拷貝到客戶端連接 socket。splice()

我們先來看看 ?系統(tǒng)調(diào)用的實(shí)現(xiàn),代碼如下:splice()

splice()系統(tǒng)調(diào)用主要調(diào)用 函數(shù)進(jìn)行下一步處理,我們來分析一下 函數(shù)的實(shí)現(xiàn)。函數(shù)主要分兩種情況進(jìn)行處理,代碼如下:do_splice()``do_splice()``do_splice()


如上面代碼所示, 函數(shù)分兩種情況處理,如下:do_splice()

  1. 如果輸入端是一個(gè)管道,則調(diào)用 ?函數(shù)進(jìn)行處理。do_splice_from()

  2. 如果輸出端是一個(gè)管道,則調(diào)用 ?函數(shù)進(jìn)行處理。do_splice_to()

下面我們分別來說明這兩種情況的處理過程。

1. 輸入端是一個(gè)管道

如果輸入端是一個(gè)管道(也就是說從管道拷貝數(shù)據(jù)到輸出端句柄),那么將會調(diào)用 ?函數(shù)進(jìn)行處理, 函數(shù)的實(shí)現(xiàn)如下:do_splice_from()``do_splice_from()

如果輸出端是一個(gè)普通文件,那么 將會指向 函數(shù)。如果輸出端是一個(gè) socket,那么 將會指向 函數(shù)。out->f_op->splice_write()``generic_file_splice_write()``out->f_op->splice_write()``generic_splice_sendpage()

下面將以 ?函數(shù)作為分析對象, 函數(shù)會調(diào)用 ?進(jìn)行下一步處理,如下所示:generic_file_splice_write()``generic_file_splice_write()``__splice_from_pipe()

我們接著來分析 ?函數(shù)的實(shí)現(xiàn):__splice_from_pipe()

對 ?函數(shù)進(jìn)行簡化后,邏輯就很簡單。主要過程如下:__splice_from_pipe()

  1. 獲取管道環(huán)形緩沖區(qū)(管道的實(shí)現(xiàn)可以參考《圖解 |Linux進(jìn)程通信 - 管道實(shí)現(xiàn)》一文)。

  2. 調(diào)用 ?函數(shù)把管道環(huán)形緩沖區(qū)的數(shù)據(jù)拷貝到輸出端的文件中。pipe_to_file()

所以,輸入端是一個(gè)管道的調(diào)用鏈如下:

2. 輸出端是一個(gè)管道

如果輸出端是一個(gè)管道(也就是說將輸入端與管道綁定),那么將會調(diào)用 ?函數(shù)進(jìn)行處理, 函數(shù)的實(shí)現(xiàn)如下:do_splice_to()``do_splice_to()

如果輸入端是一個(gè)普通文件,那么 將會指向 函數(shù)。如果輸出端是一個(gè) socket,那么 將會指向 函數(shù)。in->f_op->splice_read()``generic_file_splice_read()``in->f_op->splice_read()``sock_splice_read()

下面將以 ?函數(shù)作為分析對象, 函數(shù)會調(diào)用 ?進(jìn)行下一步處理,如下所示:generic_file_splice_read()``generic_file_splice_read()``__generic_file_splice_read()

__generic_file_splice_read()函數(shù)的代碼比較長,為了更易于分析,所以對其進(jìn)行了精簡。從精簡后的代碼可以看出, 函數(shù)主要完成 4 個(gè)步驟:__generic_file_splice_read()

  1. 查找要綁定的頁緩存是否已經(jīng)存在(已經(jīng)從硬盤同步到頁緩存)。

  2. 如果還有沒有同步到內(nèi)核的頁緩存,那么申請新的頁緩存。

  3. 如果頁緩存與硬盤的數(shù)據(jù)不一致,那么先從硬盤同步到頁緩存。

  4. 調(diào)用 ?函數(shù)將頁緩存與管道綁定。splice_to_pipe()

所以最終會調(diào)用 ?函數(shù)將頁緩存與管道綁定,我們來看看 ?函數(shù)的實(shí)現(xiàn):

splice_to_pipe()函數(shù)代碼雖然比較長,但是邏輯很簡單,就是將管道的環(huán)形緩沖區(qū)與文件的頁緩存進(jìn)行綁定,這樣就能過通過管道的讀端來讀取頁緩存的數(shù)據(jù)。

所以,輸出端是一個(gè)管道的調(diào)用鏈如下:

總結(jié)

本文主要介紹了 ?的原理與實(shí)現(xiàn), 是 ?的一種實(shí)現(xiàn)。希望通過本文,能夠讓讀者對 ?有更深入的理解。splice``splice``零拷貝技術(shù)``零拷貝技術(shù)

當(dāng)然本文也忽略了很多實(shí)現(xiàn)的細(xì)節(jié),所以在閱讀的過程中遇到某些細(xì)節(jié)不理解的時(shí)候,可以直接閱讀源代碼來解疑。





一文讀懂零拷貝技術(shù)|splice原理與實(shí)現(xiàn)的評論 (共 條)

分享到微博請遵守國家法律
梧州市| 海丰县| 永靖县| 江津市| 会东县| 乐亭县| 盐池县| 靖安县| 佛坪县| 宁武县| 句容市| 禹城市| 襄城县| 金川县| 遂宁市| 信宜市| 泗水县| 佳木斯市| 六安市| 大埔县| 灯塔市| 大化| 旬邑县| 雷州市| 阿合奇县| 偏关县| 濮阳市| 望谟县| 丹寨县| 布尔津县| 工布江达县| 五莲县| 泸州市| 阳信县| 犍为县| 神木县| 尼木县| 马边| 岳阳县| 昌乐县| 木兰县|