2009-10-22 133 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); 
}