簡體   English   中英

父級在linux shell上等待先前的子級進程

[英]Parent waits for previous child process on linux shell

我有一個程序可以派生一個進程,並確定子進程是否應該在前台和后台運行。 我在分叉之前調用信號函數來處理子信號,以確保死子進程不會變成僵屍。

到目前為止,我的程序運行良好,它會創建一個子進程,並在每當用戶輸入帶有“&”的命令時在后台運行它,並在每當用戶輸入不帶有“&”的命令時在前台運行它。

但是,我發現了一個非常有趣的行為。 假設我調用了以下操作序列:

sleep 5 &
ls

第一條命令可以正常工作,父進程無需等待睡眠5完成。 但是,當我運行“ ls”時,它將打印該文件夾中的所有文件(這很好),但是外殼卡住了,等待先前的“ sleep 5&”完成...

為什么會發生這種情況? 我的子進程和父進程(分叉后)的代碼如下所示:

 if (pid == 0)
 {
      // child process, execute stuff
      execv();
 } 
 else if (pid > 0) 
 {
      // parent process: call waitpid to wait for foreground child
 }

我試圖做一些研究,但找不到任何可以幫助我的東西。 我嘗試通過在execv()之前調用子進程來使用“ set session-id”,但是它阻止了子進程在終端上打印任何內容。 任何幫助將不勝感激。 謝謝!

    #define _XOPEN_SOURCE 700
    #include <unistd.h>
    #include <signal.h>
    #include <stdio.h>
    #include <stdbool.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/wait.h>

    void run_command(void)
    {
        char *cmd = NULL, *arg;
        size_t n, l;
        bool background;
        pid_t child;

        l = getline(&cmd, &n, stdin);
        cmd[l-1] = 0;
        l--;

        if (cmd[l-1] == '&') {
            background = true;
            cmd[l-1] = 0;
            l--;
        }
        else
            background = false;

        arg = strchr(cmd, ' ');
        if (arg) {
            *arg = 0;
            arg++;
        }

        child = fork();

        if (child) {
            if (!background)
                waitpid(child, NULL, 0);
        }
        else {
            execlp(cmd, cmd, arg, NULL);
            exit(-1);
        }

        free(cmd);
    }

    int main(void)
    {
        sigset_t set;
        struct sigaction sig;

        sigemptyset(&set);
        sig.sa_handler = SIG_DFL;
        sig.sa_mask = set;
        sig.sa_flags = SA_NOCLDWAIT;
        sigaction(SIGCHLD, &sig, NULL);

        while(!feof(stdin)) run_command();
    }

這按預期工作:

hdante@aielwaste:~/code$ ./shell 
pwd
/home/hdante/code
ls /home
hdante
sleep 5
ls /
bin    dev   initrd.img      lib32   lost+found  opt   run      srv  usr      vmlinuz.old
boot   etc   initrd.img.old  lib64   media       proc  sbin     sys  var
cdrom  home  lib         libnss3.so  mnt         root  selinux  tmp  vmlinuz
sleep 5&
xedit&
ls /
bin    dev   initrd.img      lib32   lost+found  opt   run      srv  usr      vmlinuz.old
boot   etc   initrd.img.old  lib64   media       proc  sbin     sys  var
cdrom  home  lib         libnss3.so  mnt         root  selinux  tmp  vmlinuz

在上面的示例中,sleep 5正確阻止,而sleep 5&和xedit&則沒有。

如果不查看代碼,就不可能知道問題出在哪里。 但是請注意我處理僵屍進程的方式:我在sa_flags中使用SA_NOCLDWAIT,因此不需要跟蹤pid。 另外,我等待使用waitpid()的前台子進程。 我認為這就是問題所在。 您的代碼可能正在調用wait()而不是waitpid()。 區別在於wait()等待所有的孩子。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM