国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

從用戶模式角度看零拷貝

whatsns / 2905人閱讀

摘要:調用返回導致上下文從內核切換回用戶模式,現在數據存儲在用戶地址空間的緩沖區,并且可以再次開始向下復制數據。在內核版本中,套接字緩沖區描述符被修改,以適應這些需求下稱為零拷貝。

? 到目前為止,每個人都聽說過Linux下所謂的零拷貝功能,但我遇到有些人對這個主題沒有完全理解,正因為如此,我決定寫幾篇文章來更深入研究下這個問題,希望能夠闡明這個有用的特性;這本文中,我們將從用戶模式的應用程序角度來看看零拷貝,故省去復雜的內核級別細節。

什么是零拷貝?

為了更好的理解問題的解決方案,我們需要首先來理解下問題本身,讓我們來看看網絡客戶端下載存儲在d?mon服務器的一個文件的簡單過程,下面是一些實例代碼:

read(file, tmp_buf, len);
write(socket, tmp_buf, len);

看起來很簡單,你可能認為只有兩個系統調用并沒有太多的開銷,實際上這與實際情況相差甚遠。在這兩個調用背后,數據至少被復制了四次,并且執行了幾乎數量一樣多的用戶/內核上下文的切換(實際上這個過程還要更加復雜,但這里我只想保持簡單),為了更好的了解涉及的過程,請看圖1,上半部分表示上下文切換,下半部分表示數據復制操作

圖1所示,兩個系統調用過程中的數據復制。

第一步: 讀系統調用導致用戶空間切換到內核空間,第一次數據復制由DMA引擎執行,該引擎讀取文件內容并且存儲到內核地址空間緩沖區

第二步:數據從內核緩沖區復制到用戶緩沖區,然后讀系統調用返回。調用返回導致上下文從內核切換回用戶模式,現在數據存儲在用戶地址空間的緩沖區,并且可以再次開始向下復制數據。

第三步:寫系統調用導致上下文從用戶模式切換到內核模式。第三次數據復制是再次執行把數據復制到內核地址空間的緩沖區,不過這一次,數據被放到了不同的緩沖區,這個緩沖區是跟套接字相關聯的。

第四步:寫系統調用返回,創造了第四次上下文切換。第四次數據復制是由DMA引擎獨立、異步的從內核緩沖區傳遞到協議引擎。你可能會問自己,獨立和異步是什么意思?數據不是在系統調用之前傳輸的嗎?系統調用返回,實際上并不能保證傳輸,甚至不能保證傳輸的開始。這僅僅意味著以太網驅動程序在隊列中有空閑的描述符,并且接受了我們的數據進行傳輸,在我們之前可能有很多的數據包在排隊,除非驅動程序/硬件實現優先級的環或隊列,否則數據是以先到先出的方式傳輸的(上圖中DMA復制說明了最后一個復制可以延遲的事實)

正如您看到的,很多的數據復制并不是需要的,可以消除一些重復的復制,以減少開銷并提高性能;作為一個驅動程序開發人員,我使用一些硬件的高級特性,可以完全繞開主存儲器直接傳輸數據到另一個設備,這個特性消除了系統內存中的數據復制,是一個好東西,但不是所有的硬件都支持它。還存在磁盤數據必須重新轉換成網絡數據的問題,這帶來了一些復雜性;為了消除開銷,我們可以從消除內核與用戶緩沖區之間的一些數據復制開始。

消除復制的一種方法就是跳過read調用,轉而調用mmap,列如:

tmp_buf = mmap(file, len);
write(socket, tmp_buf, len);

為了更好的了解所涉及的過程,請看圖2,上下文切換保持不變。

圖2,mmap調用

第一步:mmap系統調用導致文件內容被DMA引擎復制到內核緩沖區中。然后與用戶進程共享緩沖區,而不需要在內核和用戶內存空間之間執行任何數據復制。

第二步:寫系統調用使內核將原始內核緩沖區中的數據復制到與套接字關聯的內核緩沖區中。

第三步:第三次復制發生在DMA引擎將數據從內核套接字緩沖區傳遞到協議引擎時。

使用mmap代替read,我們將內核的數據復制減少了一半,這在傳輸大量數據時產生了相當好的效果,然而這種改進并不是沒有代價的,使用mmap+write方式存在一些隱藏的缺陷。當您在內存映射了一個文件時, 這時如果正好有一個進程使用write修改了這個文件使之變小了,這時有可能會訪問到映射文件之外的內存,進程將收到SIGBUS信號而退出,這不是網絡服務器最理想的操作,有兩種方法可以解決這個問題 。

第一種方法是為SIGBUS信號安裝一個信號處理程序,然后在處理程序中簡單地調用return。通過這樣做,write系統調用返回它在被中斷之前所寫的字節數,errno設置為成功。讓我指出,這將是一個壞的解決方案,只看到了問題的表面而沒有解決問題的本質,因為SIGBUS信號表明這個過程出了嚴重問題,所以我不鼓勵將此作為解決方案使用。

第二種解決方案涉及從內核中租借文件(在Microsoft Windows中稱為“opportunistic locking”)。這是解決這個問題的正確方法。通過在文件描述符上使用租借,可以在特定文件上使用內核。然后,您可以從內核請求讀/寫租約。當另一個進程試圖截斷您要傳輸的文件時,內核會向您發送實時信號RT_SIGNAL_LEASE信號。它告訴您,內核正在破壞該文件上的寫或讀租約。在程序訪問無效地址并被SIGBUS信號殺死之前,寫調用被中斷。write調用的返回值是在中斷之前寫入的字節數,errno將被設置為success。下面是一些示例代碼,展示了如何從內核獲得租約:

if(fcntl(fd, F_SETSIG, RT_SIGNAL_LEASE) == -1) {
    perror("kernel lease set signal");
    return -1;
}
/* l_type can be F_RDLCK F_WRLCK */
if(fcntl(fd, F_SETLEASE, l_type)){
    perror("kernel lease set type");
    return -1;
}

您應該在mmaping文件之前獲得您的租約,并在完成之后破壞您的租約。這是通過使用F_UNLCK的租賃類型調用fcntl F_SETLEASE來實現的。

Sendfile

在內核版本2.1中,引入了sendfile系統調用,以簡化通過網絡和兩個本地文件之間的數據傳輸。sendfile的引入不僅減少了數據復制,也減少了上下文切換。像這樣使用它:

sendfile(socket, file, len);

為了更好地了解所涉及的流程,請看圖3

圖3,用Sendfile代替讀和寫

第一步:sendfile系統調用導致文件內容被DMA引擎復制到內核緩沖區中。然后內核將數據復制到與套接字關聯的內核緩沖區中。

第二步:第三次復制發生在DMA引擎將數據從內核套接字緩沖區傳遞到協議引擎時。

您可能想知道,如果另一個進程截斷了我們通過sendfile系統調用傳輸的文件,會發生什么情況。如果我們不注冊任何信號處理程序,sendfile調用只返回它在中斷之前傳輸的字節數,errno將被設置為成功。

但是,如果在調用sendfile之前從內核獲得文件的租約,則行為和返回狀態完全相同。在sendfile調用返回之前,我們還得到了RT_SIGNAL_LEASE信號。

到目前為止,我們已經能夠避免讓內核復制幾個副本,但是仍然只剩下一個副本。這也能避免嗎?當然,在硬件的幫助下。為了消除內核所做的所有數據重復,我們需要一個支持收集操作的網絡接口。這僅僅意味著等待傳輸的數據不需要在連續內存中;它可以分散在不同的內存位置。在內核版本2.4中,套接字緩沖區描述符被修改,以適應這些需求——Linux下稱為零拷貝。這種方法不僅減少了多個上下文切換,還消除了處理器所做的數據重復。對于用戶級應用程序,沒有任何變化,所以代碼仍然是這樣的:

sendfile(socket, file, len);

為了更好地了解所涉及的流程,請看圖4

圖4,支持gather的硬件可以從多個內存位置組裝數據,從而消除另一個副本

第一步:sendfile系統調用導致文件內容被DMA引擎復制到內核緩沖區中。

第二步:沒有數據復制到套接字緩沖區中。相反,只有包含有關數據位置和長度信息的描述符被附加到套接字緩沖區,DMA引擎直接將數據從內核緩沖區傳遞到協議引擎,從而消除了剩余的最終副本。

因為數據實際上仍然是從磁盤復制到內存,從內存寫出去,有些人可能會說這不是一個真正的零拷貝。但是,從操作系統的角度來看,這是零副本,因為數據不會在內核緩沖區之間重復。當使用零副本時,除了避免復制之外,還可以獲得其他性能優勢,例如更少的上下文切換、更少的CPU數據緩存污染和沒有CPU校驗和計算。

Linux下的zero copy的實現還遠未完成,在不久的將來可能會發生變化。應該添加更多的功能。例如,sendfile調用不支持向量傳輸,服務器(如Samba和Apache)必須使用多個sendfile調用并設置TCP_CORK標志。TCP_CORK也與TCP_NODELAY不兼容,當我們想給數據添加頭信息時使用。這是一個很好的例子,說明了一個vectored調用可以消除對多個sendfile調用的需求和當前實現強制執行的延遲。

當前sendfile中一個相當令人不快的限制是,在傳輸大于2GB的文件時不能使用它。這樣大的文件在今天并不少見,而且在退出時必須復制所有的數據是相當令人失望的。因為sendfile和mmap方法在本例中都不可用,所以sendfile64在未來的內核版本中非常有用。

結論

盡管有一些缺點,但是zero-copy sendfile是一個有用的特性,我希望您已經發現本文提供了足夠的信息,可以開始在您的程序中使用它

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/77083.html

相關文章

  • Node - 異步IO和事件循環

    摘要:它是在的基礎上改進的一種方案,通過對文件描述符上的事件狀態進行判斷。檢索新的事件執行與相關的回調幾乎所有情況下,除了關閉的回調函數,它們由計時器和排定的之外,其余情況將在此處阻塞。執行事件的,例如或者。 前言 學習Node就繞不開異步IO, 異步IO又與事件循環息息相關, 而關于這一塊一直沒有仔細去了解整理過, 剛好最近在做項目的時候, 有了一些思考就記錄了下來, 希望能盡量將這一塊的...

    MyFaith 評論0 收藏0
  • 前端初學基礎知識 3

    摘要:根據瀏覽器設備的繪制限制來更新動畫,回調的次數常是每秒次。鼠標移入則停止自動改變樹枝狀態,轉為由鼠標的橫縱坐標控制。基本的深拷貝方法數組,等方法,新增運算符對象思路是把對象拆開分別賦值,同樣可以使用新增運算符,循環等。 canvas動畫 ???????動畫的形成:先畫出一幅圖,改變其中的一些參數,重新繪制圖片...不斷的重復形成動畫。 fillStyle:設置或返回填充繪畫的顏色,漸...

    Chao 評論0 收藏0

發表評論

0條評論

whatsns

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<