您的位置:首页 > 其它

孤儿进程、僵死进程

2016-05-03 19:17 344 查看
进程终止

有3种正常终止方法、2中异常终止方法。

正常终止:

1 main函数内执行return语句。

2 调用exit函数,其操作包括调用各终止处理程序(调用atexit时登记),关闭所有标准IO流。(exit用于结束正在运行的整个程序,它将参数返回给OS,把控制权交给操作系统;而return
是退出当前函数,返回函数值,把控制权交给调用函数)

3 调用_exit系统调用函数。exit函数也调用此函数。

异常终止:

1 调用abort函数,产生SIGABRT信号。

2 进程接收到某个信号而终止。进程本身如调用abort函数、其他进程和内核都能产生转送到某一进程的信号。例如进程越出其地址空间访问存储单元,或者除以0,内核就会为该进程产生相应的信号。

不管进程如何终止,最后都会执行内核中的一段代码,它为相应进程关闭所有打开的描述符,释放进程所使用的存储器等。

我们希望终止进程能够通知其父进程它是怎么终止的,对于exit和_exit函数,这依靠传递给它的退出状态(exit status)参数来实现。

在异常终止情况,内核(而非进程)产生一个指示其异常终止原因的终止状态。

孤儿进程与僵死进程:

如果父进程在子进程之前终止,子进程变为孤儿进程,那么子进程的父进程都改变为init进程,有init进程领养。实现方法:进程即将终止时,内核遍历检查所有活动进程,判断它是否正要终止的进程的子进程,若是则将其父进程ID改为1,即init进程ID。一旦子进程终止,init进程调用wait函数取得其终止状态。

如果子进程在父进程之前终止,父进程如何得到子进程的终止状态?由于内核为每个终止进程都保存了信息,所以父进程调用wait和waitpid函数可以得到这些信息,包括进程ID,终止状态,以及cpu使用时间总量。

如果父进程未调用wait / waitpid,对终止的子进程进行善后处理,那么这些子进程成为僵死进程,那么保留的那段信息就不会释放,其进程号一直被占用,但系统能用的进程号有限,如果大量产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程。

解决方法:

把产生大量僵死进程的那个父进程杀掉(通过kill发送SIGTERM或者SIGKILL信号),它产生的僵死进程就变成了孤儿进程,这些孤儿进程会被init进程接管,init进程会wait()这些孤儿进程,释放它们占用的系统进程表中的资源。

具体方法

(1)SIGCHILD信号

#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<signal.h>
#include<stdio.h>

static void SIGCHLD_process(int signo);
int main()
{
pid_t pid;
if((pid=fork())<0){
printf("fork error\n");
}
if(signal(SIGCHLD,SIGCHLD_process)==SIG_ERR)
printf("signal error"),exit(1);

if(pid==0){
printf("child process id %d\n",getpid());
exit(0);
}

printf("father process id %d  will sleep 2s\n",getpid());
sleep(2);

system("ps -o pid,ppid,state,tty,command");
exit(0);
}
void SIGCHLD_process(int signo){
pid_t pid;
while((pid=wait(NULL))>0)
printf("child process %d  terminal\n",pid);
}


(2)fork两次

原理是将子进程成为孤儿进程,从而其的父进程变为init进程,通过init进程可以处理僵尸进程。



#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
int main(){
pid_t pid;
if((pid=fork())<0){
printf("fork error\n");
exit(1);
}
else if(pid==0){//first child
if( (pid=fork())<0){
printf("fork error\n");
exit(0);
}
else if(pid>0){
printf("first child id %d exit",getpid());
exit(0);//parent from second fork ==first child exit
}
sleep(2);//sleep for 2s waitfor parent exit
printf("second child id %d ,parent id %d\n",getpid(),getppid());
exit(0);

}
if(waitpid(pid,NULL,0)!=pid){//wait for first child
printf("waitpid error\n");
exit(1);
}
system("ps -o pid,ppid,state,tty,command");
exit(0);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: