關於LINUX殭屍程式的出現和原理

gaopengtttt發表於2016-03-14
殭屍程式出現在父程式沒有回收子程式的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來防止殭屍程式


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2057203/,如需轉載,請註明出處,否則將追究法律責任。

相關文章