如何判断popen启动的流程何时完成?
我将描述符(从在popen返回的FILE *上调用的fileno())传递给调用fstat()的函数,并使用返回的值来确定要读取的内容。令人惊讶的是,如果存在延迟(例如,单步执行调试器),这实际上有效,但如果在popen之后立即调用,则返回文件大小为零。所以我需要一些方法来等待所有输出准备好 - 我该怎么做?我假设我不能调用pclose(),即使它等待,因为那时描述符不再有效。
更新:实际上,如果我假装管道调用上的fstat()失败,似乎代码工作正常 - 问题似乎是fstat()没有失败,正如预期的那样。所以我真正想要的是一种判断描述符是否为管道的方法 - fstat返回st_mode = 0(期待S_IFIFO!)
答案 0 :(得分:2)
这不起作用(至少在Linux系统上不行)。
fileno(3) - ed命令的文件描述符(由popen(3)给出)是pipe(7)。所以它不可寻找,fstat(2)不会给它任何重要的大小。
如果您需要这些细粒度的信息,请不要使用popen
,而是调用基础系统调用pipe(2),fork(2),execve(2),waitpid(2)然后您可以使用poll(2)。
如果您坚持使用popen
,您仍可以poll
fileno
;但是没有标准的方法来获取它的pid(使用waitpid
)这就是你应该直接使用syscalls(2)的原因。
我想fstat
- 管道不应该提供普通文件,如果成功则不应该为fifo(7),因此st.st_mode & S_IFMT == S_IFIFO
上的特殊情况会检测到这种情况。
答案 1 :(得分:2)
如果您没有从管道中读取,则子流程很可能从不终止。管道末端之间的缓冲区相当小。因此,当子进程写入输出时,缓冲区将填充,子进程将在write()
调用中阻塞。然后你就会陷入僵局。父进程在从管道读取之前等待子进程终止,子进程被阻塞,直到父进程从管道读取,因此无法终止。
答案 2 :(得分:1)
在类似unix的操作系统中,父进程在其子进程终止时收到SIGCHLD。见this tutorial
您还可以在管道描述符上select()检查是否有要读取的数据。当管道关闭时,“读取就绪”事件的数据为零is generated。
答案 3 :(得分:1)
也许您有一些特殊的原因想要从popen
确定管道上可用的数据量,但这通常不可用,而不是预期的用例。 popen
(在读取模式下)旨在与尽可能快地输出数据流的程序一起使用(注意:如果你不在,它们的缓冲区填满时它们会在管道上阻塞#39} ; t立即阅读)然后在他们完成后退出,为您的读者生成EOF
。这给你很大的灵活性;您可以使用基于行的读取函数,例如fgets
或getline
,读取while流直到EOF
,或者使用fread
读取大块并准备好进行简短的读取最后一个。
答案 4 :(得分:0)
我不知道这是否有帮助,但是在类似的情况下,我想存储popen()的输出。
void live(void) { // scan and read the dongle
FILE *dong; // dongle
char *c;
char cmd[] = "rtl_power -f 88M:108M:5k -1 -";
c = buf; // externally allocated buffer
dong = popen(cmd,"r");
while (!feof(dong)) {
*c = fgetc(dong);
c++;
}
pclose(dong);
textsize = (int) (c-buf);
printf("Read %i bytes\n",textsize);
}
有点拖尾文件,将其复制到buf []。它已经工作了几天,我什至在Sourceforge上发布了该程序。运行Linux,Debian和Raspbian。