從 Linux 檔案系統快取中刪除特定檔案?

從 Linux 檔案系統快取中刪除特定檔案?

我知道我可以刪除 Linux 檔案系統快取中的所有內容,但是有沒有一種方法可以只刪除一個特定檔案?或阻止檔案被快取?或告訴進程不要快取它寫入的任何檔案?

我有一個進程讀取很多小檔案並寫入一個大檔案。我想將小文件保留在緩存中以避免磁碟查找,並且我不關心緩存大文件。

答案1

潛在方法#1 - F_DROP_CACHES

我發現了 2012 年的一個方法,該方法在此郵件主題中討論了 Linux 核心的建議補丁:回覆:[RFC 補丁] fs:實作每個檔案刪除快取

摘抄

Cong> 這是實作每個檔案刪除快取的補丁草案。

有趣的。那麼我可以從流程外部執行此操作嗎?我是一名系統管理員,所以我的視角是在系統面臨壓力時注意到、發現並修復效能問題。

Cong> It introduces a new fcntl command  F_DROP_CACHES to drop  
Cong> file caches of a specific file. The reason is that currently  
Cong> we only have a system-wide drop caches interface, it could  
Cong> cause system-wide performance down if we drop all page caches  
Cong> when we actually want to drop the caches of some huge file.

如何知道檔案使用了多少快取?當在繁忙的系統上運行時,這會對效能產生什麼影響?這個補丁為我們帶來了什麼,因為我認為一旦系統面臨記憶體壓力,虛擬機器應該已經放棄快取了...

Cong> 以下是這個補丁的小測試案例:

該線程包括一個測試用例和 Linux 核心中多個文件的實際補丁,其中添加了一個附加函數來fs/drop_caches.c調用drop_pagecache_file(struct file *filp).然後可以透過前端工具fnctl.c透過命令存取此功能F_DROP_CACHES。本例呼叫此函數:

file_drop_caches(filp, arg);

它處理與給定文件關聯的所有快取的刪除。從文件中include/linux/mm.h

void file_drop_caches(struct file *filp, unsigned long which);
那這個可以用嗎?

我沒有發現任何證據表明這個補丁曾經進入過主要的 Linux 核心程式碼儲存庫,因此只有當您願意自己重新編譯 Linux 核心時,這個選項才似乎可用。

可能的方法 #2 - 使用 dd

在同一線程中,另一位用戶提到了一種完全不同的方法,該方法利用dd.

以下為摘錄從那封電子郵件

這是有用的功能。雖然不是已經提供了嗎 POSIX_FADV_DONTNEED?此功能已新增至GNU dd (8.11) 一年前

以下是該補丁中的範例:
  • 建議刪除整個檔案的緩存

     $ dd if=ifile iflag=nocache count=0
    
  • 確保整個文件的刪除緩存

     $ dd of=ofile oflag=nocache conv=notrunc,fdatasync count=0
    
  • 刪除部分檔案的快取

     $ dd if=ifile iflag=nocache skip=10 count=10 of=/dev/null
    
  • 僅使用預讀快取傳輸數據

     $ dd if=ifile of=ofile iflag=nocache oflag=nocache
    
測試一下

我並不是 100% 肯定如何測試這一點,但我想出了以下方法。

  1. 製作一個 100MB 的文件

    $ dd if=/dev/urandom of=sample.txt bs=100M count=1
    
  2. 追蹤文件存取使用fatrace

    $ sudo fatrace | grep sample.txt
    
  3. 運行top以便我們可以監視記憶體使用情況,並注意可用量。

    $ top
    
  4. 開啟文件,記下現在的可用內存量。請注意fatrace該文件的sample.txt

    $ cat sample.txt > /dev/null
    
  5. 從記憶體中刪除文件,記下現在的可用記憶體量。注意 的輸出fatrace

    $ sudo dd of=/home/saml/tst/162600/sample.txt \
        oflag=nocache conv=notrunc,fdatasync count=0
    

例子

在 1 號航站樓:
$ dd if=/dev/urandom of=sample.txt bs=100M count=1
1+0 records in
1+0 records out
104857600 bytes (105 MB) copied, 7.37996 s, 14.2 MB/s

$ ls -l sample.txt 
-rw-rw-r--. 1 saml saml 104857600 Oct 17 22:54 sample.txt
在 2 號航站樓:
$ top
...
KiB Mem:   7968336 total,  6900956 used,  1067380 free,   267080 buffers
...
在 3 號航站樓:
$ sudo fatrace | grep sample.txt
現在開啟檔案 ,sample.txt並記下 RAM 的大小。在 1 號航站樓。
$ cat sample.txt > /dev/null
在 2 號航站樓:
KiB Mem:   7968336 total,  7011896 used,   956440 free,   267336 buffers
fatrace注意終端 #3的輸出:
cat(25940): R /home/saml/tst/162600/sample.txt
cat(25940): R /home/saml/tst/162600/sample.txt
cat(25940): RC /home/saml/tst/162600/sample.txt
現在從終端機 #4 中的 RAM 中刪除該檔案:
$ sudo dd of=/home/saml/tst/162600/sample.txt \
    oflag=nocache conv=notrunc,fdatasync count=0
fatrace注意終端 #2的輸出:
dd(26229): O /home/saml/tst/162600/sample.txt
dd(26229): CW /home/saml/tst/162600/sample.txt
注意終端機 #3 中的 RAM:
KiB Mem:   7968336 total,  6908364 used,  1059972 free,   267364 buffers

因此,RAM 中檔案消耗的所有內容似乎都被釋放了。

潛在方法 #3 - python-fadvise

感謝 @frostchutz 的評論,還有另一個工具,一個名為 Python 腳本的工具,[pyadvise][4]它提供了比上述方法更簡單的介面dd。該腳本使用相同的posix_fadvise(2)介面。

例子
$ sudo pyadvise --help
Usage: 
    pyadvise [options] [FILE]..

Options:
  -h, --help        show this help message and exit
  -w, --willneed    The specified files will be accessed in the near future
  -s, --sequential  The application expects to access the specified files
                    sequentially (with lower offsets read before higher ones)
  -d, --dontneed    The specified files will not be accessed in the near
                    future
  -r, --random      The specified files will be accessed in random order
  -o, --noreuse     The specified files will be accessed only once. Under
                    Linux, this operation is a no-op; see contrib/copyfileobj-
                    fadvise.py in the python-fadvise source tree for an
                    example on how to achieve approximately the same effect
  -n, --normal      Indicates that the application has no advice to give about
                    its access pattern for the specified files. If no advice
                    is given for an open file, this is the default assumption
  -v, --verbose     Explain what is being done

如果我們重複上述測試並pyadvise使用dd

$ pyadvise -d /home/saml/tst/162600/sample.txt

我注意到,當我使用dd.

答案2

O_DIRECT擴展@geekosaur的答案,您可以透過使用 LD_PRELOAD 和此處的程式來強制使用:http://aighi.blogspot.com/2007/04/how-to-bypass-buffer-cache-in-linux.html

該代碼適用O_DIRECT於所有文件。然而,只需添加一些更多的 strncmp 邏輯,__do_wrap_open您就可以選擇性地應用 O_DIRECT。

免責聲明:我沒有對此進行測試。

答案3

您可以使用該標誌開啟單一檔案O_DIRECT(請參閱man 2 open) — 閱讀筆記仔細閱讀該線上幫助頁的部分,並考慮您是否也想要/需要O_SYNC.

答案4

如果您想要強製檔案始終使用 O_SYNC,您可以在擴充屬性中將其標記為chattr +S $file

男人聊天:

當修改設定為「S」屬性的檔案時,變更會同步寫入磁碟;這相當於應用於檔案子集的「同步」安裝選項。

O_SYNC 強制將資料+元資料寫入磁碟緩衝區,但它仍然透過頁面快取。 O_DIRECT 繞過頁面快取。

但請注意,使用 O_DIRECT 開啟它會對效能產生不利影響,如果只是附加大文件,則差異可能很小。但是,如果大檔案在隨機位置被重寫,O_DIRECT 將對效能造成很大影響,即使考慮到它在快取中也可能會從快取中逐出一些小讀取檔案。

如果你有內存來保存所有小文件,你可以用另一種方​​式解決這個問題。確保小檔案始終在記憶體中,然後我建議將它們複製到臨時檔案系統

tmpfs 將所有內容放入內核內部緩存並增長和收縮以容納其包含的文件

相關內容