Linux

posix_fadvise 和 readahead 之間的區別

  • December 13, 2021

根據手冊頁,readahead是 Linux 特定的:

符合

readahead() 系統呼叫是特定於 Linux 的,應避免在可移植應用程序中使用它。

並且posix_fadvise是攜帶式的:

符合

POSIX.1-2001,POSIX.1-2008。請注意,在 POSIX.1-2001 TC1 中,len 參數的類型從 size_t 更改為 off_t。

但他們倆似乎都在做同樣的事情。但是,除了冒便攜性之外,交換這兩種功能的後果是什麼?

讓我們看看這些系統呼叫導致執行的程式碼。

在這裡引用mm/readahead.c

611   │ ssize_t ksys_readahead(int fd, loff_t offset, size_t count)
612   │ {
613   │     ssize_t ret;
614   │     struct fd f;
615   │
616   │     ret = -EBADF;
617   │     f = fdget(fd);
618   │     if (!f.file || !(f.file->f_mode & FMODE_READ))
619   │         goto out;
620   │
621   │     /*
622   │      * The readahead() syscall is intended to run only on files
623   │      * that can execute readahead. If readahead is not possible
624   │      * on this file, then we must return -EINVAL.
625   │      */
626   │     ret = -EINVAL;
627   │     if (!f.file->f_mapping || !f.file->f_mapping->a_ops ||
628   │         !S_ISREG(file_inode(f.file)->i_mode))
629   │         goto out;
630   │
631   │     ret = vfs_fadvise(f.file, offset, count, POSIX_FADV_WILLNEED);
632   │ out:
633   │     fdput(f);
634   │     return ret;
635   │ }

注意第 631 行:這個東西vfs_fadvise(…, POSIX_FADV_WILLNEED)在下面呼叫。

比較mm/fadvise.c

192   │ int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
193   │ {
194   │     struct fd f = fdget(fd);
195   │     int ret;
196   │
197   │     if (!f.file)
198   │         return -EBADF;
199   │
200   │     ret = vfs_fadvise(f.file, offset, len, advice);
201   │
202   │     fdput(f);
203   │     return ret;
204   │ }

這段程式碼也只是呼叫相同vfs_fadvise,所以使用posix_fadvise64(…, WILLNEED)功能上是相同的

不同之處(可能)在於當您使用任一函式的文件不合適時報告的錯誤:readahead它本身檢查文件是否可讀,映射,實際上是否有任何有用的定址操作,EBADF是否返回EINVAL

fadvise64, 後面的系統呼叫posix_fadvise, 直接呼叫vfs_fadvise, 以便在內部檢查這些東西, 並可能返回不同的錯誤。(我還沒有檢查它是否真的如此)。

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