2013-02-26 21 views
0

我有一個程序分叉一個進程,並確定子進程是否應該在前臺和後臺運行。我稱之爲信號函數來處理分岔之前的子信號,以確保死亡子進程不會變成殭屍。家長在linux shell上等待以前的子進程

到目前爲止,我的程序正常工作,它會創建一個子進程,每當用戶輸入與「&」命令,運行它的背景,每當用戶輸入而不「&」命令,運行它的前景。

但是,我發現了一個非常有趣的行爲。提供我稱爲這個操作序列:

sleep 5 & 
ls 

第一個命令將正常工作,父進程不會等待睡眠5完成。但是,當我運行「ls」時,它會打印該文件夾中的所有文件(這很好),但隨後外殼卡住了,等待先前的「睡眠5 &」完成...

爲什麼會出現這種情況?我的兒童和(分叉後)父進程的代碼看起來很像如下:

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

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

+0

有很多可能性。沒有看到更多的代碼,很難猜測問題。 – 2013-02-26 00:31:36

回答

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

這按預期方式工作:

[email protected]:~/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 

在上面的例子中,睡眠5正確塊,而睡眠5 &和XEDIT &沒有。

不看你的代碼,就不可能知道問題出在哪裏。不過要注意我處理殭屍進程的方式:我在sa_flags中使用SA_NOCLDWAIT,這樣我就不需要跟蹤pid了。另外,我使用waitpid()等待前臺子進程。這就是我認爲問題所在。很可能你的代碼調用了wait()而不是waitpid()。不同的是wait()等待所有的孩子。