我不明白为什么父进程会继续执行,即使他的子进程没有终止。
这是a.c:
if (!fork()){
execl("/bin/sh", "sh", "-c", "gnome-terminal -x ./b", (char *) 0);
}
else {
int status;
wait(&status);
if ((status & 255) == 0) printf("\nProcess regularly exited ");
printf("adios");
return 0;
}
这是b.c:
printf("hello\n");
fflush(0);
getchar();
exit(0);
父进程打印"进程定期退出"和" adios"当子进程没有终止并且等待getchar()的输入时,我不明白为什么。
最后,如何强制父进程等待b.c的执行完成?
答案 0 :(得分:3)
将评论转换为答案。
当面对一个在执行另一个程序时没有按预期工作的C程序时,一个关键问题是在shell中发生的事情'对于这个问题,这意味着:
从命令行运行sh -c "gnome-terminal …"
时,在获得提示之前需要多长时间?
它是即刻的。
所以 - 惊喜,惊喜 - 当你从C代码运行它时会发生同样的事情。 sh -c …
的shell会立即退出,因此您的父进程会发现其死亡并退出。我认为你的第二个程序是作为你分叉的过程的孙子或曾孙的运行。你有sh
运行gnome-terminal
,它可能是forks而父进程在孩子继续管理终端并且分叉运行第二个命令的shell时(或者可能没有使用)一个shell,只需执行你的第二个命令)。一个过程只能等待直接的孩子死去;它不能等待孩子的孩子或更远的后代。
现在,如果我在
while(1){}
之前的a.c
末尾添加return 0
,b.c
之前的exit(0)
末尾添加top
,{{1} }命令表示我有4个进程:2个a.c
和2个b.c
。难道不奇怪吗?
可能会发生多种事情。它可能是以前运行的剩余进程。您需要查看流程树,以了解这些流程是否相关以及它们之间的关系。
谢谢他们只是简单的剩余流程。
最后,如何强制父进程等待
b.c
的执行完成?
简洁地说,你不能让A等待B完成。你需要一种方法让A知道哪个进程是它应该等待的B。它不能直接等待它,因为B不是它自己的孩子,所以你可能最终做了一些轮询操作,看看B是否还在。这可能是使用kill()
和信号0进行测试;在Linux上,您可以在/proc
文件系统上使用iNotify(并避免轮询)。
答案 1 :(得分:1)
您可以使用信号。这是一个简单而不优雅的解决方案。
交流转换器
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
void death_handler();
int main(){
sigset_t set;
sigfillset(&set);
sigprocmask(SIG_BLOCK,&set,NULL);
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
sigprocmask(SIG_UNBLOCK, &set, NULL); //unlock SIGUSR1
signal(SIGUSR1, death_handler);
printf("my pid is %d\n", getpid());
char pid[50];
snprintf(pid, 50, "gnome-terminal -x ./b %d",(int)getpid());
if (fork() == 0){
execl("/bin/sh","sh", "-c", pid,(char *) 0);
}
else {
int status;
//nobody, apart from the other process (and anyone that sends me a SIGUSR1 signal) can tell me to exit. It has to send a SIGUSR1 signal.
pause();
//UNBLOCK ALL PREVIOUSLY BLOCKED SIGNALS
sigemptyset(&set);
sigfillset(&set);
sigprocmask(SIG_UNBLOCK, &set, NULL);
//remove ex-child handler
signal(SIGUSR1, SIG_DFL);
printf("adios\n");
return 0;
}
}
void death_handler(){
printf("ex-child dead\n");
}
这是b.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
int main(int argc, char** argv){
int xmax;
xmax = atoi(argv[1]);
printf("parent pid = %s \n", argv[1]);
fflush(0);
getchar();
kill((pid_t)xmax, SIGUSR1);
printf("sendinga signal to the ex-parent to abort pause()...\n");
exit(0);
}
这基本上会暂停父母,直到有人发出10信号。它只能被发送SIGUSR1信号的人取消暂停。
另一种解决方案可能是使用信号量。您将信号量初始化为0.父级执行等待,然后,当子进程完成后,您只需执行一个帖子(在子级中),即可释放父级。