许多 children 中只有一个 child 死了,其余的等待 ctrl + c
Only one child out of the many children die and the rest wait for ctrl + c
我正在 Linux 中的 C 中为 shell 编写代码,其中我必须实现多个管道(例如 A | B | c | D,其中 A、B、C、 D 是命令)。 shell 为每个具有相同 pgid 的命令创建一个单独的进程,并使用 pipe() 系统调用连接它们的输入和输出。一旦创建了所有 children,parent 使用 tcsetpgrp() 使这个 pgid 进入前台并进入后台。一切正常,但事实上一旦 children 执行 A、B、C、D 完成,只有处理 A 的 child1 死亡并由 sigchild 处理程序处理,而另一个 children 只是等待并且什么都不做直到我按 ctrl + c。按下 ctrl + c 后,所有其他 children 都会被信号处理程序接收,并且 sigsuspend 中的 parent 会唤醒并再次回到前台。
任何人都可以帮助我理解为什么只有 Child 1 死亡以及控制在哪里而另一个 children 没有完成?
这是 SIGINT 处理程序的代码。
void sigchld_handler(int s) {
int olderrno = errno;
sigset_t mask_all;
sigset_t prev_all;
sigfillset(&mask_all);
while ((pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
sigprocmask(SIG_BLOCK, &mask_all, &prev_all);
NoOfChildrenToBeReaped--;
sigprocmask(SIG_SETMASK, &prev_all, NULL);
}
errno = olderrno;
}
这是 parent 的代码,它创建了所需数量的 children。
//Get the pid of the first child and set it as the pgid of all the sibling children.
if (i == 0) {
pgid = pid;
}
setpgid(pid, pgid);
这里是 parent 进入后台的过程,跟踪有多少 children 将被收割,并在 sigsuspend() 之后返回前台。
if (BGProc) {
if (tcsetpgrp(STDIN_FILENO, pgid) == -1) {
printf(EXEC_ERROR, "Error in tcsetpgrp");
}
while (NoOfChildrenToBeReaped) {
sigsuspend(&masknone);
}
signal(SIGTTOU, SIG_IGN);
if (tcsetpgrp(STDIN_FILENO, getpid()) == -1) {
printf(EXEC_ERROR, "Error in tcsetpgrp");
}
}
非常感谢任何帮助。
谢谢。
这实际上是一个愚蠢的错误,而且确实是一个问题,因为用于管道的 FileDescriptors 没有正确关闭。感谢@Ctx 指出并通过评论提出好的建议
for (i = 0; i < 2 * NoOfPipes; i++)
close(pipefds[j]); //should have been "i".
估计是我忽略了"for"里面的代码,想当然了
我正在 Linux 中的 C 中为 shell 编写代码,其中我必须实现多个管道(例如 A | B | c | D,其中 A、B、C、 D 是命令)。 shell 为每个具有相同 pgid 的命令创建一个单独的进程,并使用 pipe() 系统调用连接它们的输入和输出。一旦创建了所有 children,parent 使用 tcsetpgrp() 使这个 pgid 进入前台并进入后台。一切正常,但事实上一旦 children 执行 A、B、C、D 完成,只有处理 A 的 child1 死亡并由 sigchild 处理程序处理,而另一个 children 只是等待并且什么都不做直到我按 ctrl + c。按下 ctrl + c 后,所有其他 children 都会被信号处理程序接收,并且 sigsuspend 中的 parent 会唤醒并再次回到前台。
任何人都可以帮助我理解为什么只有 Child 1 死亡以及控制在哪里而另一个 children 没有完成?
这是 SIGINT 处理程序的代码。
void sigchld_handler(int s) {
int olderrno = errno;
sigset_t mask_all;
sigset_t prev_all;
sigfillset(&mask_all);
while ((pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
sigprocmask(SIG_BLOCK, &mask_all, &prev_all);
NoOfChildrenToBeReaped--;
sigprocmask(SIG_SETMASK, &prev_all, NULL);
}
errno = olderrno;
}
这是 parent 的代码,它创建了所需数量的 children。
//Get the pid of the first child and set it as the pgid of all the sibling children.
if (i == 0) {
pgid = pid;
}
setpgid(pid, pgid);
这里是 parent 进入后台的过程,跟踪有多少 children 将被收割,并在 sigsuspend() 之后返回前台。
if (BGProc) {
if (tcsetpgrp(STDIN_FILENO, pgid) == -1) {
printf(EXEC_ERROR, "Error in tcsetpgrp");
}
while (NoOfChildrenToBeReaped) {
sigsuspend(&masknone);
}
signal(SIGTTOU, SIG_IGN);
if (tcsetpgrp(STDIN_FILENO, getpid()) == -1) {
printf(EXEC_ERROR, "Error in tcsetpgrp");
}
}
非常感谢任何帮助。
谢谢。
这实际上是一个愚蠢的错误,而且确实是一个问题,因为用于管道的 FileDescriptors 没有正确关闭。感谢@Ctx 指出并通过评论提出好的建议
for (i = 0; i < 2 * NoOfPipes; i++)
close(pipefds[j]); //should have been "i".
估计是我忽略了"for"里面的代码,想当然了