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

标签 c multithreading stdio

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

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

但是我确实担心,在线程 1 打开一个 FILE* 之后,线程 2 对 fopen 的调用将返回 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');
};

testfile.txt 包含 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");

跨各种平台,

  • file2 != file1 会得到保证吗?
  • file2 != NULL 会得到保证吗?
  • file1 是否仍然有效?
  • 这会不会有导致未定义行为的危险?
  • 这会不会有导致数据竞争的危险?

最佳答案

一次从多个文件句柄以只读方式打开同一个文件不是问题;它将按预期可靠地工作。由于文件中没有数据被修改,并且由于所有 transient 数据(例如缓冲数据、当前查找位置)都保存在 FILE 结构本身中(每个线程都有自己的单独/私有(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?

没有。

关于c - 在同一个文件上同时以读取模式打开两个 FILE 句柄,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54507454/

相关文章:

c - 1000 以下的所有 3 或 5 的倍数之和在 C 中给出错误答案

Java在另一个线程中等待一个对象

java - 将参数传递给同步块(synchronized block)的目的是什么?

c - 为什么这个结构数组只访问第一个元素并显示其余元素的段错误?

c - 使用 openMP 任务时出现意外行为

c - 需要将 c 中文件中的值转换为 int/float

java - 在Java中中断另一个线程的run方法中的一个线程

c++ - 从 C++ 二进制文件中读取返回错误值

c - 如何在这种情况下正确使用 sscanf?

c - 从文本文件读取后,结果显示不正确