========================================================
一般当一个进程终止后都会发送SIGCHLD信号给它的父进程,并由此变为僵死进程直到父进程接收了其状态报告其资源才会被系统释放;
处理方法有3种:
1. 当子进程终止时父进程接收SIGCHLD信号并调用waitpid()函数接收其状态报告,最好用sigaction(),signal()不可靠;
2. 通过函数sigaction指明标志SA_NOCLDWAIT来指定信号SIGCHLD的动作,这使得内核在调用者的子进程终止时不创建僵死进程。
3. 二次fork调用;
处理方法有3种:
1. 当子进程终止时父进程接收SIGCHLD信号并调用waitpid()函数接收其状态报告,最好用sigaction(),signal()不可靠;
2. 通过函数sigaction指明标志SA_NOCLDWAIT来指定信号SIGCHLD的动作,这使得内核在调用者的子进程终止时不创建僵死进程。
3. 二次fork调用;
================================================================================================================
引出:
fork之后子进程继承父进程的各种变量、文件描述符、会话、进程组等。(简单的复制内存??)
1. 父进程不等待子进程结束的处理方式:
signal(SIGCHLD,SIG_IGN)
忽略SIGCHLD信号,这常用于并发服务器的性能的一个技巧,因为并发服务器常常fork很多子进程,子进程终结之后需要,服务器进程去wait清理资源。
如果将此信号的处理方式设为忽略,可让内核把僵尸子进程转交给init进程去处理,省去了大量僵尸进程占用系统资源。(Linux Only)
如果将此信号的处理方式设为忽略,可让内核把僵尸子进程转交给init进程去处理,省去了大量僵尸进程占用系统资源。(Linux Only)
注意:编写守护进程时,即使fork两次,新进程由init接管,不进行signal(SIGCHLD,SIG_IGN)操作,也会产生僵尸进程。
2.父进程等待子进程结束的处理方式:
等待单一进程结束:
pid = fork(); //生成一个子进程
if (pid < 0) // error check.
handle_err();
if (pid < 0) // error check.
handle_err();
if (pid == 0)
exit (execl(....)); // child process.
else
if (wait(&ret) < 0)
perror("wait"); //parent process
exit (execl(....)); // child process.
else
if (wait(&ret) < 0)
perror("wait"); //parent process
等待多个进程:主进程中加入信号处理函数Proc_CHLD
signal(SIG_CHLD, Proc_CHLD);
void Proc_CHLD(int SIGNO)
{
int pid = -1;
int stat;
while(pid=waitpid(0, &stat, WHNONG);
}
void Proc_CHLD(int SIGNO)
{
int pid = -1;
int stat;
while(pid=waitpid(0, &stat, WHNONG);
}