我的Ubuntu Xenial系统如下:
# uname -r
4.4.0-179-generic
#
我有以下简单的 C 代码,每秒向文件写入 5 个字节,总共 5 次:
{
int fd = open("test.txt", O_WRONLY | O_TRUNC);
if (fd == -1) return -1;
int x = 0;
while (x++ < 5)
{
write(fd, "Hello", 5);
sleep(1);
}
}
我还有以下内容:
# cat /proc/sys/vm/dirty_writeback_centisecs
500
#
然而,当我tail -f test.txt
我看到输出立即出现在文件中:根据上面的内容,我预计它会在 5 秒后出现。我对此做了很多研究,发现它pdflush
不再存在,但无法找出哪个进程/线程负责在我的内核中写回脏页。
有人可以解决这个问题吗?我如何控制数据何时刷新到我的文本文件?
更新:
得到答案后以下,我测试了一下,看到了文件的修改时间。 LinuxScratch
是前面显示的代码所在的二进制文件的名称。
我们可以看到该文件确实每秒都在更新:
$ ./LinuxScratch &
[1] 1475
$ ls --time-style='+%d-%m-%Y %H:%M:%S' -l
total 104
-rwxrwxr-x 1 ubuntu ubuntu 37576 22-12-2020 19:35:46 LinuxScratch
-rw-rw-r-- 1 ubuntu ubuntu 15 22-12-2020 19:41:47 test.txt
$ ls --time-style='+%d-%m-%Y %H:%M:%S' -l
total 104
-rwxrwxr-x 1 ubuntu ubuntu 37576 22-12-2020 19:35:46 LinuxScratch
-rw-rw-r-- 1 ubuntu ubuntu 20 22-12-2020 19:41:48 test.txt
$ ls --time-style='+%d-%m-%Y %H:%M:%S' -l
total 104
-rwxrwxr-x 1 ubuntu ubuntu 37576 22-12-2020 19:35:46 LinuxScratch
-rw-rw-r-- 1 ubuntu ubuntu 25 22-12-2020 19:41:49 test.txt
$ ls --time-style='+%d-%m-%Y %H:%M:%S' -l
total 104
-rwxrwxr-x 1 ubuntu ubuntu 37576 22-12-2020 19:35:46 LinuxScratch
-rw-rw-r-- 1 ubuntu ubuntu 25 22-12-2020 19:41:49 test.txt
[1]+ Done ./LinuxScratch
$
更新2
我还发现,关于负责刷新的线程,这个答案声明它是通用的 [kworker/#.##] 内核线程负责执行写回。
更新3
阅读 LWN.net 中的文章后回答,我做了更多研究,发现通过尝试值/proc/sys/vm/dirty_expire_centisecs
(如描述的这里),然后运行watch
on /proc/vmstat
,我可以看到脏页在刷新时先增加然后减少。
$ sudo sysctl -w vm.dirty_expire_centisecs=250
$ watch -d -n 0.1 grep -e dirty /proc/vmstat
在另一个外壳中:
$ ./LinuxScratch
这表明脏页 ( nr_dirty
) 增加 1,然后在大约 2.5 秒后下降(无论哪种方式,都比默认值 3000(30 秒)要快得多)。
这页面对于参数描述也很有用。
所以都说了,接受的答案部分解释了原来的问题,我在这里的更新显示了如何演示/控制这一点。我最终希望能够以某种方式停止将内核缓冲区刷新到文件系统,只是为了查看(因此完全理解)功能,但我从接受的答案中猜想,这可能是不可能的,因为内核总是获取的方式并显示其缓存中的最新数据。
答案1
您的tail
命令还从页面缓存获取输入。页缓存的全部意义在于,进程(任何进程,不仅仅是写入文件的进程)可以从缓存中快速找到所需的数据,而无需访问磁盘。
内核pdflush
线程已被每支持设备内核线程取代。这LWN.net文章描述了变化及其背后的动机。