关闭文件指针而不关闭底层文件描述符

21
通过使用fdopen()fileno(),可以使用现有的文件描述符打开流。但是,一旦使用流打开文件,正确关闭文件的方法是关闭FILE指针,即fclose()。那么如何关闭流但保留打开的文件描述符呢?
这种行为类似于调用fflush()fileno(),然后在关闭时不再使用FILE指针。另一个问题是,如果您随后再次使用fdopen(),则会出现多个FILE指针,并且只能关闭其中一个。
2个回答

25

如果您使用的是POSIXy系统(我假定您是这样做的,因为您使用了fileno()),那么您可以使用dup()来克隆文件描述符:

int newfd = dup(fileno(stream));
fclose(stream);

或者你可以将一个重复的文件描述符交给fdopen():

FILE *stream = fdopen(dup(fd), "r");

无论哪种方式,使用FILE *关闭的另一个fd副本都不会关闭。然而,请记住位置指针是共享的,因此如果同时使用两个指针,请小心。此外,在关闭副本时,原始fd上持有的任何fcntl()锁都将被释放。


Windows和其他平台都支持fileno()! 我简直不敢相信我没有想到这个dup()解决方案,非常优雅明显。 - Matt Joiner
你不也需要将新的fd复制回原始fd,然后关闭新的fd,以便一切都恢复到关闭文件流之前的状态吗? :D 这意味着在执行fclose()之前,你需要oldfd = fileno(stream)。 - Jonathan Leffler
Jonathan,在多线程应用程序中这样做是冒险的。最好在将fd传递给fdopen之前使用dup,这样您可以确保它不会触及您的原始文件描述符。 - bdonlan
@bdonlan,可以解释一下吗?我不明白这怎么会有暴力或色情内容。 - Matt Joiner
线程A: close(42); 线程B: open(...) (返回42) 线程A: dup2(42, 54); 现在线程B的fd已被关闭并替换为线程A正在处理的内容。 - bdonlan
是的,但无论如何传递fd都无法避免这种情况。在dup和fdopen之间没有引入任何线程,您只需要确保在此期间没有线程关闭它。上面给出的代码本身并不会有竞争问题。 - Matt Joiner

1

如果其他方法失敗,dup(2) 可能有所幫助。


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