我写一个程序,它请求读取文件,然后通过TCP套接字(HTTP服务器)发送的内容。客户同时服务多个线程,它已经到了我的注意,这是完全有可能的两个客户端将同时请求相同的文件。
我的希望是,如果线程1调用fopen(path,"rb");
然后线程2还呼吁fopen(path,"rb"); // Same path.
,由于这两个在path
在读模式下打开此文件,给定的路径是有效的两个电话应该会成功。
然而,我有关注到线程1打开FILE*
后线程2对fopen
调用将NULL
返回由于存在已经是一个打开的文件句柄,并在我的HTTP服务器的情况下,这将导致客户端错误地收到404 Not Found
错误页面,而不是资源的要求,这当然是不理想的结果。
我敢肯定有办法来同步访问或共享文件,这些线程之间处理,但为了简单起见,我想能够避免执行这些更复杂的机制。
在Windows上使用MinGW-W64,我觉得这个代码:
#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之间移植)的行为,我得避免使我的代码更费解比它需要。不过当然,如果它是不可移植的行为,那么我就需要想办法的。
TL; DR:
如果“file.txt的”是一个有效的路径,然后在下面的代码:
char* path = "file.txt";
FILE* file1 = fopen(path,"r");
FILE* file2 = fopen(path,"r");
跨越多种平台,
file2 != file1
得到保障?file2 != NULL
得到保障?file1
将仍然有效?打开同一个文件从一次对多个文件句柄只读访问是没有问题的;如预期它会可靠地工作。由于文件中没有数据被修改,因为所有的过渡状态数据(例如,缓冲的数据,电流寻找位置)设置在FILE
结构本身保持(每个线程有其自己的单独的/私人FILE
结构),没有竞争条件。
将file2中!= FILE1得到保障?
是。
将file2中!= NULL得到保障?
是的(假设该文件没有得到当然的两个电话之间删除或重命名,:))
文件1将仍然有效?
是。
这会不会有造成未定义行为的危险?
没有。
这会不会有造成数据竞争的危险?
没有。