繁体   English   中英

子进程中的Execl()和父进程中的wait()

[英]Execl() in a child process and wait() in the parent process

我不明白为什么父进程即使子进程没有终止也继续执行。

这是ac:

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;
}

这是不列颠哥伦比亚省:

printf("hello\n");
fflush(0);
getchar();
exit(0);

当子进程尚未终止并且正在等待getchar()输入时,父进程会打印“定期退出的进程”和“ adios”,而我不明白为什么。

最后,如何强制父进程等待直到bc的执行完成?

将评论转换为答案。

面对无法按预期运行的C程序时,另一个关键问题是“ shell中发生了什么”。 对于这个问题,它转换为:当您从命令行运行sh -c "gnome-terminal …" ,要多长时间才能返回提示?

瞬间。

因此,令人惊讶的是,当您从C代码运行它时,也会发生同样的事情。 sh -c …的外壳会立即退出,因此您的父进程会发现它的死亡并退出。 我认为您的第二个程序是作为您分叉过程的孙代或曾孙代运行的。 您有sh ,它运行gnome-terminal ,可能会分叉,而父级会退出,而孩子继续管理终端并分叉运行第二条命令的shell(或者可能不使用shell并只是执行第二条命令)。 一个进程只能等待其直接子进程死亡。 它不能等它的孩子的孩子或更远的后代。

现在,如果我在return 0之前的ac末尾和exit(0)之前的bc末尾添加while(1){} ,则top命令指示我有4个进程: ac 2个和bc 2个。 奇怪吗?

可能会发生多种情况。 它可能是先前运行的剩余流程。 您需要查看流程树以了解那些流程是否相关以及它们之间的关系。

谢谢,他们只是剩下的过程。

最后,如何强制父进程等待直到bc的执行完成?

简而言之,您不能让A等待B完成。 您需要让A知道应该等待哪个进程B的方法。 它不能直接等待它,因为B不是它自己的孩子,因此您可能最终会进行一些轮询操作以查看B是否仍在附近。 那可能是用kill()和信号0进行测试; 在Linux上,您也许可以在/proc文件系统上使用iNotify(并避免轮询)。

您可以使用信号。 这是一个简单但不完善的解决方案。

交流电

#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");    
}

这是公元前

#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。父级执行等待,然后,子进程完成后,您只需在子级中执行一个发布,即可释放父级。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM