子进程不产生僵尸进程的方法:
方法一:
signal(SIGCHLD, SIG_IGN);父进程不必等待子进程结束,子进程由init进程负责回收
因为并发服务器常常fork很多子进程,子进程终结之后需要服务器进程去wait清理资源。如果将此信号的处理方式设为忽略,可让内核把僵尸子进程转交给init进程去处理,省去了大量僵尸进程占用系统资源。(Linux Only)
对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。在Linux下可以简单地将 SIGCHLD信号的操作设为SIG_IGN。
对于SIGCHLD信号,如果我们定义为:
1.SIG_DFL :默认的处理方式是不理会这个信号,但是也不会丢弃子进行状态,所以如果不用wait,waitpid对其子进行进行状态信息回收,会产生僵尸进程。
2.SIG_IGN:忽略,此时我们的子进程终止的时候,有init进程进程回收,所以不会产生僵尸进程。
使用signal(SIGCHLD,SIG_IGN):不要在父进程中调用wait函数,否则堵塞到所有子进程结束,且返回错误。
SIG_IGN :忽略的处理方式,这个方式和默认的忽略是不一样的语意,暂且我们把忽略定义为SIG_IGN,在这种方式下,子进程状态信息会被丢弃,也就是自动回收了,所以不会产生僵尸进程,但是问题也就来了,wait,waitpid却无法捕捉到子进程状态信息了,如果你随后调用了wait,那么会阻塞到所有的子进程结束,并返回错误ECHILD,也就是没有子进程等待。
方法二:
通过调用sigaction()函数设置sa_flag中的SA_NOCLDWAIT标志,如果设置此标志,则子进程终止时候,不产生僵尸进程,同时不向父进程发送SIGCHLD信号,我们同样不要调用wait()函数,否则wait()会一直堵塞到所有子进程终止,并返回错误。
以上两种方法:除了是否向父进程发送SIGCHLD的区别之外,其他的操作都一样,都交给init进程处理
SIGCHLD信号:
1、子进程终止的时候会向父进程发送SIGCHLD信号(只有设置SA_NOCLDWAIT时候,子进程终止的时候不向父进程发送SIGCHLD信号)
2、子进程被停止(收到SIGSTOP,SIGTSTP,SIGTTIN或者SIGTTOU),总会向父进程发送SIGCHLDX信号,
3、被停止的子进程恢复运行的时候
设置SA_NOCLDSTOP会影响2、3情况,不影响1情况