在同一个文件上同时以读取模式打开两个 FILE 句柄

Opening two FILE handles in read mode, on the same file, simultaneously

我正在编写一个程序,它接收读取文件的请求,然后通过 TCP 套接字(HTTP 服务器)发送它们的内容。跨多个线程同时为客户端提供服务,我注意到两个客户端完全有可能同时请求同一个文件。

我希望,如果线程 1 调用 fopen(path,"rb");,然后线程 2 也调用 fopen(path,"rb"); // Same path.,因为这两个线程都在 path 以读取模式打开文件,所以如果路径有效,两个调用都应该成功。

但是我确实担心在线程 1 打开 FILE* 之后线程 2 对 fopen 的调用将 return NULL 因为已经有一个打开的文件处理,并且在我的 HTTP 服务器的上下文中,这将导致客户端错误地接收到 404 Not Found 错误页面,而不是请求的资源,这当然不是期望的结果。

我确信有一些方法可以在这些线程之间同步访问或共享文件句柄,但为了简单起见,我希望能够避免实现这些更复杂的机制。

在使用 MinGW-w64 的 Windows 上,我发现这段代码:

#include <stdio.h>
int main ()
{
    FILE* handle1 = fopen("testfile.txt","rb");
    FILE* handle2 = fopen("testfile.txt","rb");
    printf("%llX\n",handle1);
    printf("%llX\n",handle2);

    char buf [8];

    for (int i = 0; i < 8; i++) buf[i] = 'X';
    fread(buf,1,8,handle1);
    for (int i = 0; i < 8; i++) putchar(buf[i]);
    putchar('\n');

    for (int i = 0; i < 8; i++) buf[i] = 'X';
    fread(buf,1,8,handle2);
    for (int i = 0; i < 8; i++) putchar(buf[i]);
    putchar('\n');
};

with testfile.txt containing File Contents 产生以下输出:

7FFE2439FA90
7FFE2439FAC0
File Con
File Con

...这就是我想要的。

但是我想知道这种行为是标准的,还是只是因为 Windows 或我的代码链接到的标准库实现的原因才按我的意愿行事。

如果它是标准的(或者,至少足够普遍,可以在 Windows 和 Linux 之间移植)行为,我可以避免让我的代码比它需要的更复杂。但是,当然,如果它不是可移植的行为,那么我确实需要弄清楚一些事情。


长话短说:

如果"file.txt"是一个有效的路径,那么在下面的代码中:

char* path = "file.txt";
FILE* file1 = fopen(path,"r");
FILE* file2 = fopen(path,"r");

跨多种平台,

一次从多个文件句柄以只读方式打开同一个文件不是问题;它将按预期可靠地工作。由于文件中没有数据被修改,并且由于所有瞬态数据(例如缓冲数据、当前查找位置)都保存在 FILE 结构本身中(并且每个线程都有自己的 separate/private FILE 结构),没有竞争条件。

Will file2 != file1 be guaranteed?

是的。

Will file2 != NULL be guaranteed?

是(假设文件在两次调用之间没有被删除或重命名,当然 :))

Will file1 still be valid?

是的。

Will this have a danger of causing undefined behavior?

没有

Will this have a danger of causing a data race?

没有