在读取之前等待 popen 子进程终止
waiting for popen subprocess to terminate before reading
如何判断 popen 启动的进程何时完成?
我正在将描述符(来自对 popen 返回的 FILE * 调用的 fileno())传递给调用 fstat() 的函数,并使用返回的值来确定要读取的量。令人惊讶的是,如果有延迟(例如,单步调试调试器),但如果在 popen 后立即调用,returns 文件大小为零,这实际上会起作用。所以我需要一些方法来等待所有输出准备就绪 - 我该怎么做?我假设我不能调用 pclose() 即使它在等待,因为这样描述符就不再有效了。
更新:实际上,如果我假装 fstat() 在管道调用中失败,代码似乎工作正常 - 问题似乎是 fstat() 没有像预期的那样失败。所以我真正想要的是一种判断描述符是否为管道的方法 - fstat returns st_mode=0(期待 S_IFIFO!)
在类似 unix 的 LOSes 中,父进程在其子进程终止时收到 SIGCHLD。参见 this tutorial
你也可以select() on the pipe descriptor to check if there's a data to read. When the pipe is closed a "read-ready" event with zero-size data is generated.
这行不通(至少在 Linux 系统上行不通)。
文件描述符(由 fileno(3)) of a popen(3)-ed command is a pipe(7). So it is not seekable, and fstat(2) 给出,不会给出任何重要的大小。
如果您需要如此细粒度的信息,请不要使用 popen
,而是调用底层系统调用 pipe(2), fork(2), execve(2), waitpid(2) then you can use poll(2)。
如果你坚持使用 popen
你仍然可以 poll
它的 fileno
;然而,没有标准的方法来获取它的 pid(使用 waitpid
)这就是为什么你应该直接使用 syscalls(2)。
我猜 fstat
-ing 一个管道不应该给出一个普通文件,而是一个 fifo(7) 如果它成功,所以 st.st_mode & S_IFMT == S_IFIFO
上的特殊情况来检测这种情况。
也许您有一些特殊原因想要确定来自 popen
的管道上可用的数据量,但这不是普遍可用的,也不是预期的用例。 popen
(在读取模式下)旨在与尽可能快地输出数据流的程序一起使用(注意:如果您不读取它,当缓冲区填满时它们会阻塞管道立即)然后在完成后退出,为您的 reader 生成 EOF
。这给了你很大的灵活性;您可以使用 fgets
或 getline
等基于行的读取函数,读取 while 流直到 EOF
,或者使用 fread
读取大块并准备好进行简短读取最后一个。
如果您不从管道读取,子进程很可能永远不会终止。管道两端之间的缓冲区相当小。因此,当子进程写入输出时,缓冲区将填满并且子进程将阻塞在 write()
调用中。那么你就会陷入僵局。父进程在从管道读取之前正在等待子进程终止,子进程被阻塞,直到父进程从管道读取,因此无法终止。
我不知道这是否有帮助,但我想存储 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.
如何判断 popen 启动的进程何时完成?
我正在将描述符(来自对 popen 返回的 FILE * 调用的 fileno())传递给调用 fstat() 的函数,并使用返回的值来确定要读取的量。令人惊讶的是,如果有延迟(例如,单步调试调试器),但如果在 popen 后立即调用,returns 文件大小为零,这实际上会起作用。所以我需要一些方法来等待所有输出准备就绪 - 我该怎么做?我假设我不能调用 pclose() 即使它在等待,因为这样描述符就不再有效了。
更新:实际上,如果我假装 fstat() 在管道调用中失败,代码似乎工作正常 - 问题似乎是 fstat() 没有像预期的那样失败。所以我真正想要的是一种判断描述符是否为管道的方法 - fstat returns st_mode=0(期待 S_IFIFO!)
在类似 unix 的 LOSes 中,父进程在其子进程终止时收到 SIGCHLD。参见 this tutorial
你也可以select() on the pipe descriptor to check if there's a data to read. When the pipe is closed a "read-ready" event with zero-size data is generated.
这行不通(至少在 Linux 系统上行不通)。
文件描述符(由 fileno(3)) of a popen(3)-ed command is a pipe(7). So it is not seekable, and fstat(2) 给出,不会给出任何重要的大小。
如果您需要如此细粒度的信息,请不要使用 popen
,而是调用底层系统调用 pipe(2), fork(2), execve(2), waitpid(2) then you can use poll(2)。
如果你坚持使用 popen
你仍然可以 poll
它的 fileno
;然而,没有标准的方法来获取它的 pid(使用 waitpid
)这就是为什么你应该直接使用 syscalls(2)。
我猜 fstat
-ing 一个管道不应该给出一个普通文件,而是一个 fifo(7) 如果它成功,所以 st.st_mode & S_IFMT == S_IFIFO
上的特殊情况来检测这种情况。
也许您有一些特殊原因想要确定来自 popen
的管道上可用的数据量,但这不是普遍可用的,也不是预期的用例。 popen
(在读取模式下)旨在与尽可能快地输出数据流的程序一起使用(注意:如果您不读取它,当缓冲区填满时它们会阻塞管道立即)然后在完成后退出,为您的 reader 生成 EOF
。这给了你很大的灵活性;您可以使用 fgets
或 getline
等基于行的读取函数,读取 while 流直到 EOF
,或者使用 fread
读取大块并准备好进行简短读取最后一个。
如果您不从管道读取,子进程很可能永远不会终止。管道两端之间的缓冲区相当小。因此,当子进程写入输出时,缓冲区将填满并且子进程将阻塞在 write()
调用中。那么你就会陷入僵局。父进程在从管道读取之前正在等待子进程终止,子进程被阻塞,直到父进程从管道读取,因此无法终止。
我不知道这是否有帮助,但我想存储 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.