C语言 如何在集合进程自己的 SIGCHLD 处理程序中获取其 PID?



我正在为大学写一个玩具外壳,我必须在后台进程结束时更新它的状态。所以我想到了让SIGCHLD处理程序这样做的想法,因为该信号是在进程结束时发送的。问题是为了实现命令jobs,我必须将状态从"正在运行"更新为"终止",首先我必须在专用于它的数组中找到该特定进程,一种方法是通过 pid 搜索,因为数组存储了jobs中显示的信息。每个条目存储进程 pid、状态(字符串)和命令本身。

现在的问题是: 有没有办法获取在结束时调用信号的进程的 pid?

现在这是我的处理程序函数的样子:

void handler(int sig){
int child_pid;
child_pid = wait(NULL);
//finds the process with a pid identical 
//to child_pid in the list and updates its status
...
}

由于wait(NULL)返回自调用以来结束的第一个进程的 pid,因此仅当另一个后台进程结束时才会更新状态,因此会更新错误的进程状态。

我们没有从wait()waitpid()函数中得到很多东西,除了它们等待流程结束之外,所以任何见解都可能会有所帮助。

虽然在信号处理程序中使用 wait 不是一个好主意,但您可以执行以下操作来完成您尝试执行的操作。

void handler(int sig){
int child_pid;
int status;
child_pid = waitpid(-1, &status, WUNTRACED | WNOHANG);
if(child_pid > 0)
{
// your code
// make sure to deal with the cases of child_pid < 0 and child_pid == 0
}
}

您正在做的事情在技术上没有错,但是,最好使用waitpid.当您使用waitpid(-1,...)时,它的工作方式与使用wait(...)类似,不仅会等待指定的进程,还会等待任何终止的进程。主要区别在于,您可以指定暂停执行WUNTRACED,直到等待集中的进程终止或停止。WNOHANG将告诉waitpid不要暂停进程的执行。您不希望您的处理程序被暂停。

如果将多个信号发送到同一进程,即由于多个子级同时终止,则看起来只发送了一个信号,因为信号处理程序不会再次执行。这是由于信号的发送方式;当一个信号被创建时,它被放入一个异常表中,然后让进程"接收"它;信号不使用队列。为了解决这个问题,您需要迭代waitpid(-1,...)调用,直到它返回 0,以确保您正在收获所有终止的子项。

此外,请注意您在哪里收获孩子(请注意,如果孩子已经被收获,那么如果您使用WNOHANG标志waitpid将返回 0)。我假设这就是导致您看到的状态仅在另一个后台进程结束时更新的行为的原因。例如,因为你正在制作一个玩具外壳,我假设你正在某处等待前台进程,如果你在那里以及你的处理程序中使用等待函数,你可能会得到两件事中的一件事发生。孩子在"等待前台进程"方法中获得收获,然后当处理程序被执行时,它没有任何收获。2,孩子在处理程序方法中收获,然后"等待前台进程"永远不会退出。

相关内容

最新更新