我的代码有问题,
我希望所有的子进程在程序启动时停止,之后我只希望索引为i
的子进程继续执行,而其他的子进程停止。
我希望按照p0、p1、p2、p3、p4、p0、p1 ....的顺序执行它们。
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <signal.h>
# include <sys/wait.h>
# define N 5
void handler(int i)
{
if (i == SIGCONT)
{
printf("signal cont\n");
}
}
int main()
{
int pid[N];
for (int i = 0; i < N; i++)
{
if ((pid[i] = fork()) == 0)
{
/* code */
while (1)
{
printf("ici fils %d\n", i);
usleep(50000);
}
}
else
{
kill(pid[i], SIGSTOP);
// kill(pid[i], SIGSTOP);
if (i == N - 1)
{
kill(pid[i], SIGCONT);
sleep(2);
kill(pid[i], SIGSTOP);
kill(pid[0], SIGCONT);
}
else
{
kill(pid[i], SIGCONT);
sleep(2);
kill(pid[i], SIGSTOP);
kill(pid[i + 1], SIGCONT);
}
// kill(pid[i], SIGKILL);
waitpid(pid[i], NULL, 0);
}
signal(SIGCONT, &handler);
}
}
2条答案
按热度按时间z31licg01#
您的代码存在以下几个问题:
1.任何通过
SIGSTOP
停止的进程都不能有为该信号注册的处理程序。注册处理程序会导致处理程序的行为 * 替换 * 停止进程的默认行为。1.为
SIGCONT
注册一个处理程序通常不是一个好主意,这样做不会阻止SIGCONT
继续进程,这是SIGCONT
的一个特殊特性,可能会让人感到惊讶,而且每当SIGCONT
被传递时,即使进程没有停止,处理程序也会触发,这通常是一种不同的惊讶。1.您只在第一次分支之后的父级中注册信号处理程序。随后分支的子级将继承这些处理程序,但第一个子级不会。除此之外,这将防止第一个子级的
pause()
被父级发送给它的信号解除阻塞。您可以让每个子级为自己注册任何所需的处理程序,也可以在第一次分支之前在父级中注册它们。1.在每个子级的
pause()
和父级的第一个kill()
之间存在竞争。子级有可能在调用pause()
之前接收到SIGCONT
,在这种情况下,它将等待 next 信号。您可以通过在派生之前在父级中阻塞SIGCONT
,并在子级中使用sigsuspend()
来防止这种情况。在这种情况下,您可能希望在从初始sigsuspend()
返回后解除对SIGCONT
的阻塞。1.父进程尝试向它尚未派生的进程发送信号(
kill(pid[i + 1], SIGCONT);
)。目前还不清楚您要实现的完整行为是什么,但您可能希望首先派生所有子级,然后才开始发送信号。
更新
关于问题的最新情况,
1.显然,您希望在子进程中重复循环,但您的代码只运行一次。这是实现我在上面建议的内容的一个很好的理由:先把所有的孩子分开,然后,分别做所有的信号。
gopyfrb32#
在 child 进程中,不使用
pause(2)
,而是使用raise(3)
向调用进程发出停止SIGSTOP
的信号。真实的上不需要注册信号处理程序。在 parent 进程中,创建 child 进程后,使用设置了
WUNTRACED
标志的waitpid(2)
等待其停止(或终止)。WIFSTOPPED(...)
宏可用于明确确定子进程的状态。WCONTINUE
标志可用于等待 child 进程继续,就像之前的WIFCONTINUED(...)
宏一样。这里是一个粗略的例子,没有任何有意义的错误处理。请注意,并发睡眠虽然简单,但从技术上讲并不是一种一致的调度方式。此程序的输出 * 可能 * 在执行之间略有不同。