dd: iflag=nocache
第一次使用無效
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
,除了兩個標誌if
和of
。對於具有列的行-
,dd_flags
這意味著dd
沒有額外的標誌(除了if
andof
)- 輸入文件
dd
是一個大文件(3.8GB),儲存在 SATA SSD 中(最大吞吐量約 500MB)。- 的輸出文件
dd
是 /dev/null。- 上表中的
Time[s]
列是實時,它是time
Bash 保留字的結果。- 我不執行同步,因為不需要 - 文件是在 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
沒有解決我的問題的相關閱讀:
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 標誌的描述也比聯機幫助頁更詳細,因此可能值得一讀。