编写我自己的玩具外壳,并试图实现作业控制。
我正在使用setpgid在子级和父级中设置子级的进程组。我的等待电话是:
pid = waitpid(-pid, &status, 0)
但是,waitpid返回-1并且perror说“没有子进程”。但是,它确实似乎每次都在等待。另外,ps输出在从shell运行时看起来正确。因为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 :(得分:13)
我在waitpid手册页中忽略了sigchld:
POSIX.1-2001指定如果 处理 SIGCHLD设置为 SIG_IGN或SA_NOCLDWAIT标志是 为SIGCHLD设置(参见sigaction(2)), 然后终止的孩子不会 成为僵尸和调用wait()或 waitpid()将阻塞直到所有 孩子们已经终止了,然后 将errno设置为ECHILD失败。( 原来的POSIX标准离开了 将SIGCHLD设置为的行为 未指定SIG_IGN。)Linux 2.6 符合此规范。 但是,Linux 2.4(及更早版本)确实如此 不:如果是wait()或waitpid()调用 在SIGCHLD被忽略时做出, 这个电话的行为就好像 SIGCHLD没有被忽视 是,呼叫阻塞直到下一个 孩子终止然后返回 进程ID和该子进程的状态。
答案 1 :(得分: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;
}
答案 2 :(得分:2)
我在尝试为我的计算机科学课程实现一个小外壳时找到了这个线程,并且想我会分享对我有用的东西。我收到以下错误:
Waitpid error: No child processes
就我而言,我使用的是计算机系统提供的包装器:
程序员的透视教科书。为了解决我的错误,我更改了Waitpid
中的csapp.c
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);
}