FCLOSE()/ pclose函数()可以阻断某些文件指针
题
fclose()
ing其文件描述符块,直到子进程结束(大概是因为流已经结束)后调用dup()
这里。
FILE *f = popen("./output", "r");
int d = dup(fileno(f));
fclose(f);
然而,通过手动执行pipe()
,fork()
,所述execvp()
的popen()
,然后dup()
ing管道的读文件描述符,关闭原始不会阻塞。
int p[2];
pipe(p);
switch (fork()) {
case 0: {
char *argv[] = {"./output", NULL};
close(p[0]);
dup2(p[1], 1);
execvp(*argv, argv);
}
default: {
close(p[1]);
int d = dup(p[0]);
close(p[0]);
}
}
为什么会发生这种情况,我怎么能关闭FILE *
从popen()
返回,并在其位置使用文件描述符?
<强>更新强>
我知道,文件说,使用pclose()
,但是fclose()
块为好。此外,我在glibc的代码戳左右,而pclose()
只是调用fclose()
。的行为是相同的,或fclose()
是否pclose()
使用。
解决方案 2
与所述答案的一般性失望迄今(I可以 RTFM ,tyvm),I “VE彻底调查此,通过步进和读取的glibc 源。
在的glibc pclose()
直接调用fclose()
没有额外的效果,所以2级的呼叫是一样的。事实上,你可以使用pclose()
和互换fclose()
。我敢肯定,这是纯粹的演进实施巧合,以及使用pclose()
来关闭FILE *
返回从popen()
仍建议。
在神奇的是在popen()
。在glibc的FILE *
s包含有指向跳转表到适当的函数来处理此类呼叫的fseek()
,fread()
,和相关fclose()
的。当调用popen()
,比fopen()
使用的人用不同的跳转表。所述close
构件在该跳转表指向一个特殊功能_IO_new_proc_close
,其上的PID存储在区域调用waitpid()
通过FILE *
指向。
下面是我的glibc版本,我已经与正在发生的事情上做笔记注释相关的调用堆栈:
// linux waitpid system call interface
#0 0x00f9a422 in __kernel_vsyscall ()
#1 0x00c38513 in __waitpid_nocancel () from /lib/tls/i686/cmov/libc.so.6
// removes fp from a chain of proc files
// and waits for the process of the stored pid to terminate
#2 0x00bff248 in _IO_new_proc_close (fp=0x804b008) at iopopen.c:357
// flushes the stream and calls close in its jump table
#3 0x00c09ff3 in _IO_new_file_close_it (fp=0x804b008) at fileops.c:175
// destroys the FILEs buffers
#4 0x00bfd548 in _IO_new_fclose (fp=0x804b008) at iofclose.c:62
// calls fclose
#5 0x00c017fd in __new_pclose (fp=0x804b008) at pclose.c:43
// calls pclose
#6 0x08048788 in main () at opener.c:34
所以它的短路,使用popen()
,返回FILE *
不能关闭,即使你dup()
它的文件描述符,因为它会阻止,直到子进程终止。当然,在此之后,你会留下一个文件描述符其中将包含一个管不管孩子的过程管理,以write()方法来终止它之前。
如果不从fread()
返回的文件指针popen()
ing,底层管道不会被触动,它是安全的fileno()
使用文件描述符,并通过调用pclose()
完成了。
其他提示
http://linux.die.net/man/3/popen
<强>的函数,pclose()函数等待关联的进程终止并返回命令的退出状态通过wait4()返回。强>
由于pclose函数()要返回退出状态,它必须等待子终止并生成一个。由于FCLOSE()调用函数,pclose(),同样适用于FCLOSE()为您服务。
如果您fork和exec和你自己做休息,你不最终调用函数,pclose()(直接或间接),所以没有在接近的时间等待。但是请注意,除非你的程序设置为忽略SIGCHLD,你的进程将不会终止(而不是它会去僵尸),直到孩子一样。但至少你的成本将运行第一个退出。
通过FILE*
返回的popen()
应由pclose()
被关闭,而不是由fclose()
。然后,对于pclose()
的说明文件:
在pclose函数()函数等待 相关进程终止和 返回命令的退出状态 如通过wait4()返回。
所以等待是的两件事情pclose()
确实,除了关闭文件描述符之一。 close()
做的只有一件事:它关闭描述符
在回答您的第二个问题,我想你可以使用fileno()
返回的描述符。有没有必要dup()
它。你用它完成后,pclose()
原来的。