我写了一个小的 C 程序,它创建一个子进程,然后使用 popen 运行一个 shell 命令。我创建了一个信号处理程序来等待子进程结束,而父进程只是在无限循环中运行。当我在 popen 系统调用后调用 'sleep(5)' 时, sleep 调用不起作用。
相反,如果我将 sleep 调用放在 popen 之前,那么它就可以工作了。此外,如果我删除信号处理程序并只等待父进程中的子进程,那么就没有问题(即 sleep 在任何地方都可以正常运行)。
//Assume all required header files and function prototypes added
int main()
{
int pid,status;
signal(SIGCHLD,reaper);
pid = fork();
if(pid == 0)
runCommand();
while(1);
}
void runCommand()
{
FILE *pipen;
char *buffer;
buffer = (char*) malloc(100);
/*sleep #1*/ sleep(5);
if ((pipen = popen("uname -a", "r")) == NULL) {
perror("\nError during shell command execution: ");
exit(0);
}
/*sleep #2*/ sleep(5);
fgets(buffer, 100, pipen);
/*sleep #3*/ sleep(5);
printf("\n%s\n",buffer);
exit(0);
}
void reaper(int signal)
{
int status;
waitpid(-1,&status,WNOHANG);
}
当我运行上面的程序时,sleep #1 工作并且进程在给定的时间内休眠。我通过观察打印命令结果(通过 printf 语句)所花费的时间来了解这一点。 但是对于 sleep #2 和 sleep #3,我希望进程休眠,但这似乎并没有发生,因为命令的结果会立即打印在控制台上。
可以通过仅保留 sleep #2 或 sleep #3 调用并移除其他两个 sleep 调用来观察该行为。
有人知道为什么会这样吗?
最佳答案
popen()
通过派生一个子进程来执行 /bin/sh -c "uname -a"
来工作。当该子进程退出时,该进程会收到一个 SIGCHLD
信号。这会中断 sleep()
调用并运行您的 reaper
函数。
我没能在任何 Linux 或 POSIX 文档中找到它,但它在 SunOS documentation 中:
The signal handler for
SIGCHLD
should be set to default when usingpopen()
. If the process has established a signal handler forSIGCHLD
, it will be called when the command terminates. If the signal handler or another thread in the same process issues await(2)
call, it will interfere with the return value ofpclose()
. If the process's signal handler forSIGCHLD
has been set to ignore the signal,pclose()
will fail and errno will be set toECHILD
.
您应该在子进程中将 SIGCHLD
处理程序设置回默认值。
void runCommand()
{
FILE *pipen;
char *buffer;
signal(SIGCHLD, SIG_DFL);
buffer = (char*) malloc(100);
/*sleep #1*/ sleep(5);
if ((pipen = popen("uname -a", "r")) == NULL) {
perror("\nError during shell command execution: ");
exit(0);
}
/*sleep #2*/ sleep(5);
fgets(buffer, 100, pipen);
/*sleep #3*/ sleep(5);
printf("\n%s\n",buffer);
exit(0);
}
关于c - popen 函数调用后 sleep 在子进程中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55696970/