我正在编写一个程序,该程序接受读取文件的请求,然后通过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
仍然有效吗?答案 0 :(得分:2)
一次打开同一文件以从多个文件句柄进行只读访问不是问题;它会按预期可靠地工作。由于没有修改文件中的任何数据,并且由于所有瞬态状态数据(例如,缓冲数据,当前位置)都保存在FILE
结构本身中,并且每个线程都有自己单独的/私有的FILE
结构),没有竞争条件。
将保证file2!= file1吗?
是的
是否可以保证file2!= NULL?
是的(当然,假设没有在两次调用之间删除或重命名文件)
file1仍然有效吗?
是的
这会有引起不确定行为的危险吗?
否。
这会有引起数据争夺的危险吗?
否。