在Windows中控制C++ std::fstream创建的文件句柄的可继承性

4
在Windows中,使用CreateProcess创建进程时,可以将true作为bInheritHandles参数传递。
CreateProcess( , , , , bInheritHandles, , , , )

这意味着所有标记为可继承的文件句柄将确实被子进程继承。
我们如何控制由C++的std::fstream类创建的底层文件句柄是否可继承?

1
你不能这样做。如果你打算继承,使用CreateFile()函数。 - Michael Chourdakis
然而,至少如果使用MSVC,有一种方法可以先从HANDLE获取FILE,然后将std::fstream绑定到该FILE - SoronelHaetir
何必这么麻烦呢?既然你必须使用API,就只用API,不要同时使用API和std。 - Michael Chourdakis
@MichaelChourdakis,fstream对象更容易使用。 通过使用运算符 <<>>,您可以自动解析和字符串化变量。 - Mercalli
1
@Mercalli 所有标准对象与 API 相比在功能上都有所限制,只适用于基本级别的处理。在一个完整的项目中,您需要更多的能力,这意味着需要使用 API。此外,您仍然可以使用缓冲区级别的流函数,然后使用 API 将缓冲区写入文件。 - Michael Chourdakis
2个回答

3
C运行时默认创建可继承的句柄。
ofstream outFile("filename.txt") ;
CreateProcess("program.exe", ..., true, ...) ; //program.exe will inherit the above file handle

因此,如果您希望一个句柄被继承,您无需采取任何措施。

如果您不希望一个句柄被继承,则需要使用WinAPI函数SetHandleInformation将句柄的HANDLE_FLAG_INHERIT标志设置为自己,如下所示:

FILE* filePtr = fopen("filename.txt", "w") ;
SetHandleInformation( (HANDLE)_get_osfhandle(_fileno(filePtr)), HANDLE_FLAG_INHERIT, 0) ;
ofstream outFile(filePtr) ;

在上面的第三行中,构造函数ofstream(FILE*)是Visual Studio中存在的标准扩展(我不知道其他编译器是否有),该构造函数使filePtr现在归outFile所有,因此调用outFile.close()也会关闭filePtr。您可以完全忘记filePtr变量。
文档:fopen_fileno_get_osfhandleSetHandleInformation

2
或者,你可以通过传递一个 PROC_THREAD_ATTRIBUTE_LISTCreateProcess,来白名单指定你想要被继承的句柄,而不是“黑名单”所有不应该被继承的句柄(可能会错过操作系统或库句柄,这些句柄超出了你的控制)。 - zett42

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接