簡體   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