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

时间:2019-02-03 20:50:34

标签: c multithreading stdio

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

我的希望是,如果线程1调用fopen(path,"rb");,然后线程2也调用fopen(path,"rb"); // Same path.,则由于这两个都在读取模式下以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的{​​{1}}产生以下输出:

File Contents

...这就是我想要的。

但是我想知道此行为是标准行为还是只是我想要的行为,这是由于某些有关Windows或我的代码链接到的标准库实现的原因。

如果这是标准行为(或者至少很常见,可以在Windows和Linux之间移植),那么我将避免使我的代码变得更加复杂。但是,当然,如果不是可移植的行为,那么我确实需要弄清楚一些事情。


TL; DR:

如果“ file.txt”是有效路径,则使用以下代码:

7FFE2439FA90
7FFE2439FAC0
File Con
File Con

在各种平台上

  • 是否可以保证char* path = "file.txt"; FILE* file1 = fopen(path,"r"); FILE* file2 = fopen(path,"r");
  • 是否可以保证file2 != file1
  • file2 != NULL仍然有效吗?
  • 这会有引起不确定行为的危险吗?
  • 这会有引起数据争夺的危险吗?

1 个答案:

答案 0 :(得分:2)

一次打开​​同一文件以从多个文件句柄进行只读访问不是问题;它会按预期可靠地工作。由于没有修改文件中的任何数据,并且由于所有瞬态状态数据(例如,缓冲数据,当前位置)都保存在FILE结构本身中,并且每个线程都有自己单独的/私有的FILE结构),没有竞争条件。

  

将保证file2!= file1吗?

是的

  

是否可以保证file2!= NULL?

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

  

file1仍然有效吗?

是的

  

这会有引起不确定行为的危险吗?

否。

  

这会有引起数据争夺的危险吗?

否。