2009-10-22 130 views
5

編寫我自己的玩具殼,並碰到試圖執行作業控制的碰撞。waitpid()在等待進程組時出現無子進程錯誤

我正在設置孩子的過程組,同時使用setpgid設置孩子和父母的過程組。我的等待電話是:

pid = waitpid(-pid, &status, 0) 

但是,waitpid返回-1,perror表示「沒有子進程」。但是,它似乎每次都在等待。另外,從shell輸出時,ps輸出看起來是正確的。由於ps父母的過程像我期望的那樣是kbsh。

% ps -o pid,ppid,pgrp,session,tpgid,comm 
Forking 
In Parent: Setting process group to 20809 of process 20809 with setpgid 
In Child Processes, pid of child process is 20809 
in Child: Setting process group to 20809 of process 20809 with setpgid 
Requesting that Process Group 20809 becomes the foreground process with tcsetpgrp 
Waiting for job with process group 20809 
    PID PPID PGRP SESS TPGID COMMAND 
12002 32573 12002 12002 20809 zsh 
20808 12002 20808 12002 20809 kbsh 
20809 20808 20809 12002 20809 ps 
Wait Error: No child processes 
Restoring Shell process group 20808 to forground 

有人看到我在做什麼錯了嗎?如果需要可以發佈更多代碼...

+0

似乎與-1以及-pid – 2009-10-22 16:15:42

+0

當時ignorning SIGCHILD發生,那就是它不工作的原因:-P – 2009-10-22 18:02:00

回答

9

我忽略SIGCHLD,從waitpid函數手冊頁:

POSIX.1-2001 specifies that if the disposition of SIGCHLD is set to SIG_IGN or the SA_NOCLDWAIT flag is set for SIGCHLD (see sigaction(2)), then children that terminate do not become zombies and a call to wait() or waitpid() will block until all children have terminated, and then fail with errno set to ECHILD. (The original POSIX standard left the behaviour of setting SIGCHLD to SIG_IGN unspecified.) Linux 2.6 conforms to this specification. However, Linux 2.4 (and earlier) does not: if a wait() or waitpid() call is made while SIGCHLD is being ignored, the call behaves just as though SIGCHLD were not being ignored, that is, the call blocks until the next child terminates and then returns the process ID and status of that child.

+0

感謝您回答這個問題,自從文章[here](http://www.gnu.org/software/libc/manual/html_node/Implementing-a-Shell.html#Implementing-a-殼牌)似乎已經過時。 – 2012-10-20 15:13:07

2

您不必設置進程組ID。孩子默認繼承父母的pid作爲組。 當你等待,你需要等待父進程的PID:

int main(int argc, char **argv) 
{ 
    pid_t pid; 
    int stat; 

    if ((pid = fork())) 
    { 
     printf("PARENT: %d | CHILD: %d\n", getpid(), pid); 
     waitpid(-getpid(), &stat, 0); 
     printf("DONE: %m\n"); 
    } 
    else 
    { 
     printf("CHILD: %d\n", getpid()); 
     sleep(3); 
    } 
    return 0; 
} 
+0

http://www.gnu.org/s/libc/manual/html_node/Implementing-a-Shell.html#Implementing-a-Shell - 好像說我知道。 「由於每個進程都是分叉的,因此應該通過調用setpgid」 – 2009-10-22 16:03:13

+0

「將自己置於新的進程組中,因爲進程組是如何控制前臺和後臺的。 – 2009-10-22 16:04:20

2

我發現這個線程,而試圖實現一個微小的殼對於我的計算機科學課程,我想我會分享對我有用的東西。我收到以下錯誤:

Waitpid error: No child processes 

就我而言,我是通過計算機系統提供的包裝: 程序員的角度教科書。要修正我的錯誤,我在csapp.c改變Waitpid

pid_t Waitpid(pid_t pid, int *iptr, int options) 
{ 
    pid_t retpid; 

    if ((retpid = waitpid(pid, iptr, options)) < 0) 
     unix_error("Waitpid error"); 
    return(retpid); 
} 

pid_t Waitpid(pid_t pid, int *iptr, int options) 
{ 
     pid_t retpid; 

     retpid = waitpid(pid, iptr, options); 
     if (retpid < 0 && errno != ECHILD) 
       unix_error("Waitpid error"); 
     return(retpid); 
}