如何使 Linux 上的 `write()` 系统调用立即生效?

How to make `write()` system call on Linux immediately effective?

我正在为 C 编写 REPL(read-execute-print-loop)。我尝试维护一个 header 文件,以便我可以在以前的函数的基础上定义新函数。每当我定义一个新函数时,我都会得到一个新的临时文件,如下所示:

#include "/tmp/header.h"

int foo() {
    return func() * func();
}

/tmp/header.h 就像:

int func();
int foo();

其中 func() 是先前定义的函数。

所以我需要在 header_fileno 上一次又一次地调用 write()。我担心的是——在我调用 write(header_fileno, buf, wrsize) 之后,buf 的内容是否可能 存储在某个内核缓冲区 而不是 被写入实际文件?因为如果发生这种情况,我不能指望 header 给出 up-to-date 声明。对于源文件,我也有同样的担忧。如果发生这种情况,有没有办法让它立即生效?

根据 Linux man page,无法保证 write 会将您的数据提交到磁盘。使用fsync(或关闭文件)将写入的数据刷新到磁盘。 (lseek 也可能有用,如果你只想使用一个文件描述符。)

但是,如果您要经常修改文件的内容,正如您在 REPL 中所期望的那样,您可能希望将它们存储在内存中,这样您就可以更轻松地操作它们。

同样,您可能希望以另一种形式存储其信息,而不是将实时 REPL 代码存储为文本,这样您就可以更轻松地访问和更改它。

您可以安全地假设任何进程,包括当前进程,在您调用 write() 之后调用 read() 将看到更新的文件,即使该文件仍在内核缓冲区,未完全写入磁盘。 POSIX mandates 此行为:

If a read() of file data can be proven (by any means) to occur after a write() of the data, it must reflect that write(), even if the calls are made by different processes.

话虽如此,如果您使用 stdio 函数,这并不适用,它可能会在写入之前缓冲数据。如果您的系统崩溃,它也不保证您的数据不会丢失或损坏;如果您需要该保证,则必须使用 fsync() 或使用 O_SYNC.

打开文件