ris*_*shi 1 c unix linux process
我在电子书中读到waitpid(-1,&status,WNOHANG)应该放在while循环中,这样如果多个子进程同时退出,它们都会被收获.
我通过同时创建和终止2个子进程并通过waitpid收到它而不使用循环来尝试这个概念.这些都被收获了.
问题是,将waitpid放在循环中是否非常必要?
#include<stdio.h>
#include<sys/wait.h>
#include<signal.h>
int func(int pid)
{
if(pid < 0)
return 0;
func(pid - 1);
}
void sighand(int sig)
{
int i=45;
int stat, pid;
printf("Signal caught\n");
//while( (
pid = waitpid(-1, &stat, WNOHANG);
//) > 0){
printf("Reaped process %d----%d\n", pid, stat);
func(pid);
}
int main()
{
int i;
signal(SIGCHLD, sighand);
pid_t child_id;
if( (child_id=fork()) == 0 ) //child process
{
printf("Child ID %d\n",getpid());
printf("child exiting ...\n");
}
else
{
if( (child_id=fork()) == 0 ) //child process
{
printf("Child ID %d\n",getpid());
printf("child exiting ...\n");
}
else
{
printf("------------Parent with ID %d \n",getpid());
printf("parent exiting ....\n");
sleep(10);
sleep(10);
}
}
}
Run Code Online (Sandbox Code Playgroud)
是.
好的,我会详细说明.
每次调用waitpid都会收到一个,只有一个孩子.由于您将调用放在信号处理程序中,因此无法保证在执行第一个信号处理程序之前第二个子项将退出.对于两个过程是好(当你完成挂起的信号将被处理),但更多的,则可能是两个孩子将完成,而你还在处理一个又一个.由于信号未排队,您将错过通知.
如果发生这种情况,你就不会收获所有孩子.为了避免这个问题,引入了循环建议.如果您希望看到它发生,请尝试与更多孩子一起运行您的测试.你跑的越多,你就越有可能看到问题.
有了这个,让我们谈谈其他一些问题.
首先,你的信号处理程序调用printf.这是一个重要的禁忌.很少有函数是信号处理程序安全的,printf绝对不是一个.您可以尝试使信号处理程序更安全,但更安全的方法是放入一个仅设置标志的信号处理程序,然后在wait主程序的流程中进行实际调用.
由于您的主要流向是,通常情况下,调用选择/ epoll的,一定要查找pselect和epoll_pwait,并了解他们在做什么和为什么需要他们.
更好(但特定于Linux),查找signalfd.您可能根本不需要信号处理程序.
编辑添加:循环不会改变两个信号传递合并到一个处理程序调用的事实.它做的是这一个调用处理所有挂起的事件.
当然,一旦出现这种情况,你必须使用WNOHANG.导致信号合并的相同工件也可能导致您处理尚未传递信号的事件.
如果发生这种情况,那么一旦你的第一个信号处理程序存在,它将再次被调用.但是,这次没有未决事件(因为事件已经被循环提取).如果您没有指定WNOHANG,您的wait块和程序将无限期地卡住.
| 归档时间: |
|
| 查看次数: |
686 次 |
| 最近记录: |