Dd

dd: iflag=nocache 第一次使用無效

  • September 27, 2022

iflag=nocache的標誌dd似乎只在第二次以後才生效。

我不明白為什麼。

我在想也許它與預讀記憶體有關,但它沒有解釋下表中的結果:

Results - Effect of iflag=nocache: from big SATA SSD file to /dev/null:
Test_Name                dd_flags       Time[s]  time/dd exit status
w/ iflag=nocache         iflag=nocache  6.95     0
again w/ iflag=nocache   iflag=nocache  6.94     0
first w/o iflag=nocache  -              6.94     0
2nd w/o iflag=nocache    -              2.60     0
3nd w/o iflag=nocache    -              2.49     0
first w/ iflag=nocache   iflag=nocache  2.71     0
2nd w/ iflag=nocache     iflag=nocache  6.94     0
3rd w/ iflag=nocache     iflag=nocache  6.94     0

關於底部的 3 個測試/行:

  • 第一次iflag=nocache使用,然後仍然使用記憶體(由於它花費的時間很快)。
  • 最後兩次嘗試iflag=nocache花費了很長時間(即沒有記憶體),這意味著他們可能沒有使用預讀記憶體,所以預讀記憶體可能不是這裡的問題。
  • iflag=nocache標誌似乎有效,因為隨後使用它的嘗試要慢得多,這意味著沒有使用記憶體。

筆記:

  • 上表中的列dd_flags顯示了提供給 的所有標誌dd,除了兩個標誌ifof。對於具有列的行-dd_flags這意味著dd沒有額外的標誌(除了ifand of
  • 輸入文件dd是一個大文件(3.8GB),儲存在 SATA SSD 中(最大吞吐量約 500MB)。
  • 的輸出文件dd是 /dev/null。
  • 上表中的Time[s]列是實時,它是timeBash 保留字的結果。
  • 我不執行同步,因為不需要 - 文件是在 PC 啟動之前寫入的。
  • 我不清空作業系統頁面記憶體(使用echo 1 >|/proc/sys/vm/drop_caches),因為我想避免完全記憶體失效。

我嘗試刪除整個文件的記憶體,如所示info dd- 似乎有效:

Results - Effect of iflag=nocache: from big SATA SSD file to /dev/null:
Test_Name                  dd_flags               Time[s]  time/dd exit status
w/ iflag=nocache           iflag=nocache          6.95     0
again w/ iflag=nocache     iflag=nocache          6.95     0
first w/o iflag=nocache    -                      6.94     0
2nd w/o iflag=nocache      -                      2.60     0
3nd w/o iflag=nocache      -                      2.49     0
Drop cache for whole file  iflag=nocache,count=0  0.14     0
first w/ iflag=nocache     iflag=nocache          6.94     0
2nd w/ iflag=nocache       iflag=nocache          6.94     0
3rd w/ iflag=nocache       iflag=nocache          6.94     0

版本:

$ dd --version | head -1
dd (coreutils) 8.32

沒有解決我的問題的相關閱讀:

dd“直接”與“nocache”

https://www.gnu.org/software/coreutils/manual/html_node/dd-invocation.html#dd-invocation

那是因為iflag=nocache刪除記憶體……它被讀取之後,而不是之前。

如果您使用 strace,您可以看到這一點:

# strace dd iflag=nocache … |& grep -Pi 'read|dontneed'
[…]
read(0, "\0"..., 65536) = 65536
read(0, "\0"..., 65536) = 65536
fadvise64(0, 393216, 131072, POSIX_FADV_DONTNEED) = 0
read(0, "\0"..., 65536) = 65536
read(0, "\0"..., 65536) = 65536
fadvise64(0, 524288, 131072, POSIX_FADV_DONTNEED) = 0
read(0, "\0"..., 65536) = 65536
read(0, "\0"..., 65536) = 65536
fadvise64(0, 655360, 131072, POSIX_FADV_DONTNEED) = 0
[…]

每次讀取都帶有一個POSIX_FADV_DONTNEED範圍,該範圍涵蓋了先前已讀取的內容。

它與讀取不完全匹配,因為 POSIX_FADV_DONTNEED 需要與 dd 使用的塊大小不同的對齊方式。但最終它仍然會丟棄先前讀取的塊的記憶體。

因此,如果您的意圖是讀取未記憶體的數據,此 iflag 將無濟於事。(*)

相反,目的是不記憶體已讀取的內容,也不替換之前已記憶體的其他內容。這是一種在不過多干擾現有記憶體的情況下複製或流式傳輸大文件的方法。

man 2 posix_fadvise這樣描述它:

POSIX_FADV_DONTNEED

指定數據近期不會被訪問。

POSIX_FADV_DONTNEED嘗試釋放與指定區域關聯的記憶體頁面。例如,在流式傳輸大文件時,這很有用。程序可能會周期性地請求核心釋放已被使用的記憶體數據,這樣更有用的記憶體頁面不會被丟棄。

丟棄部分頁面的請求將被忽略。最好保留需要的數據而不是丟棄不需要的數據。如果應用程序要求考慮丟棄數據,則 offset 和 len 必須是頁面對齊的。

所以它是針對已經使用(已經被dd讀取)但不保存在記憶體中的數據,以免丟棄更多有用的東西。


(*)

info dd將此範例列為一種無需讀取即可刪除整個文件的記憶體的方法:

dd if=ifile iflag=nocache count=0

nocache 標誌的描述也比聯機幫助頁更詳細,因此可能值得一讀。

引用自:https://unix.stackexchange.com/questions/718912