僵尸进程出现在父进程没有回收子进程的PCB的时候,这个时候子进程已经结束,但是父进程没有回收他,保存了一份子进程的PCB在父进程的内核空间中。
僵尸进程占用的是一个PCB结构体的内存空间,所以占用量不会太大,但是过多的僵尸进程就会出现内存泄露,解决的办法就是给父进程发送一个终止的信号
如 9) SIGKILL,2) SIGINT , 15) SIGTERM信号,只要父进程终止了,那么僵尸进程的PPID就变成了init进程那么自然init进程回收了子进程的PCB
来看一段代码:
#include<stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
void serror( const char *ichar,int i)
{
perror(ichar);
exit(i);
}
int main(void)
{
pid_t pid;
int i,c,p;
for(i = 0;i < 10;i++)
{
if((pid = fork()) == 0)
{
break;
}
else if(pid < 0)
{
serror("forkerror",1);
}
}
if(pid == 0)
{
while(c < 5)
{
c += 1;
printf("child process is %d\n",getpid());
sleep(1);
}
}
if(pid > 0)
{
while(p < 20)
{
p += 1;
printf("parent process is %d\n",getpid());
sleep(1);
}
}
}
这个程序建立了10个子进程但是没有使用wait/waitpid会后子进程PCB。运行后我们发现如下:
gaopeng 3902 3630 0 06:17 pts/25 00:00:00 ./a.out
gaopeng 3903 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
gaopeng 3904 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
gaopeng 3905 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
gaopeng 3906 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
gaopeng 3907 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
gaopeng 3908 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
gaopeng 3909 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
gaopeng 3910 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
gaopeng 3911 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
gaopeng 3912 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
10个僵尸子进程。但是等到20秒后父进程结束,也就没有了。那么改进如下:
#include<stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
void serror( const char *ichar,int i)
{
perror(ichar);
exit(i);
}
void do_sig(int signo)
{
int status;
pid_t pid;
while((pid = waitpid(0,&status,WNOHANG))>0)
{
if(WIFEXITED(status))
{
printf("child %d exit normal %d\n",pid,WEXITSTATUS(status));
}
else if(WIFSIGNALED(status))
{
printf("child %d cancel by signal %d\n",pid,WTERMSIG(status));
}
}
}
int main(void)
{
pid_t pid;
int i,c,p;
for(i = 0;i < 10;i++)
{
if((pid = fork()) == 0)
{
break;
}
else if(pid < 0)
{
serror("forkerror",1);
}
}
if(pid == 0)
{
while(c < 10)
{
c += 1;
printf("child process is %d\n",getpid());
sleep(1);
}
return i;
}
if(pid > 0)
{
struct sigaction act;
act.sa_handler=do_sig;
sigemptyset(&act.sa_mask);
act.sa_flags=0;
sigaction(SIGCHLD,&act,NULL);
while(p < 20)
{
p += 1;
printf("parent process is %d\n",getpid());
sleep(1);
}
}
}
主要为加入了WAITPID来防止僵尸进程
僵尸进程占用的是一个PCB结构体的内存空间,所以占用量不会太大,但是过多的僵尸进程就会出现内存泄露,解决的办法就是给父进程发送一个终止的信号
如 9) SIGKILL,2) SIGINT , 15) SIGTERM信号,只要父进程终止了,那么僵尸进程的PPID就变成了init进程那么自然init进程回收了子进程的PCB
来看一段代码:
#include<stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
void serror( const char *ichar,int i)
{
perror(ichar);
exit(i);
}
int main(void)
{
pid_t pid;
int i,c,p;
for(i = 0;i < 10;i++)
{
if((pid = fork()) == 0)
{
break;
}
else if(pid < 0)
{
serror("forkerror",1);
}
}
if(pid == 0)
{
while(c < 5)
{
c += 1;
printf("child process is %d\n",getpid());
sleep(1);
}
}
if(pid > 0)
{
while(p < 20)
{
p += 1;
printf("parent process is %d\n",getpid());
sleep(1);
}
}
}
这个程序建立了10个子进程但是没有使用wait/waitpid会后子进程PCB。运行后我们发现如下:
gaopeng 3902 3630 0 06:17 pts/25 00:00:00 ./a.out
gaopeng 3903 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
gaopeng 3904 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
gaopeng 3905 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
gaopeng 3906 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
gaopeng 3907 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
gaopeng 3908 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
gaopeng 3909 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
gaopeng 3910 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
gaopeng 3911 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
gaopeng 3912 3902 0 06:17 pts/25 00:00:00 [a.out] <defunct>
10个僵尸子进程。但是等到20秒后父进程结束,也就没有了。那么改进如下:
#include<stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
void serror( const char *ichar,int i)
{
perror(ichar);
exit(i);
}
void do_sig(int signo)
{
int status;
pid_t pid;
while((pid = waitpid(0,&status,WNOHANG))>0)
{
if(WIFEXITED(status))
{
printf("child %d exit normal %d\n",pid,WEXITSTATUS(status));
}
else if(WIFSIGNALED(status))
{
printf("child %d cancel by signal %d\n",pid,WTERMSIG(status));
}
}
}
int main(void)
{
pid_t pid;
int i,c,p;
for(i = 0;i < 10;i++)
{
if((pid = fork()) == 0)
{
break;
}
else if(pid < 0)
{
serror("forkerror",1);
}
}
if(pid == 0)
{
while(c < 10)
{
c += 1;
printf("child process is %d\n",getpid());
sleep(1);
}
return i;
}
if(pid > 0)
{
struct sigaction act;
act.sa_handler=do_sig;
sigemptyset(&act.sa_mask);
act.sa_flags=0;
sigaction(SIGCHLD,&act,NULL);
while(p < 20)
{
p += 1;
printf("parent process is %d\n",getpid());
sleep(1);
}
}
}
主要为加入了WAITPID来防止僵尸进程