linux下zombie进程

来源:互联网 发布:淘宝客开通 编辑:程序博客网 时间:2024/05/20 23:32

一个zombie进程也成过渡进程,是指已结束运行,但尚未被清除的进程。当使用fork建立子进程时,由于子进程有可能会比父进程晚结束,子进程有可能会成为zombie进程。为避免这种情况发生可以在父进程中调用wait()函数或waitpid()函数使子进程先结束,而让父进程有机会了解子进程结束时的状态,并自动清除zombie进程。

wait(等待子进程中断或结束)  相关函数 waitpid,fork  表头文件  #include<sys/types.h>  #include<sys/wait.h>  定义函数 pid_t wait (int * status);  函数说明  wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一起返回。如果不在意结束状态值,则参数status 可以设成NULL。子进程的结束状态值请参考下面的waitpid()。  返回值  如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno 中。

WIFEXITED(status)如果子进程正常结束则为非0值。
WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED 来判断是否正常结束才能使用此宏。
WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真
WTERMSIG(status)取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。
WIFSTOPPED(status)如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。
WSTOPSIG(status)取得引发子进程暂停的信号代码,

waitpid(等待子进程中断或结束)
相关函数 wait,fork
表头文件
#include<sys/types.h>
#include<sys/wait.h>
定义函数 pid_t waitpid(pid_t pid,int * status,int options);
函数说明
waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用waitpid()时子进程已经结束,则waitpid()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数status 可以设成NULL。参数pid 为欲等待的子进程识别码,其他数值意义如下:
pid<-1 等待进程组识别码为pid 绝对值的任何子进程。
pid=-1 等待任何子进程,相当于wait()。
pid=0 等待进程组识别码与目前进程相同的任何子进程。
pid>0 等待任何子进程识别码为pid 的子进程。
参数option 可以为0 或下面的OR 组合:
WNOHANG 如果没有任何已经结束的子进程则马上返回,不予以等待。WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。
子进程的结束状态返回后存于status,底下有几个宏可判别结束情
况:
WIFEXITED(status)如果子进程正常结束则为非0 值。
WEXITSTATUS(status)取得子进程exit()返回的结束代码,一
般会先用WIFEXITED 来判断是否正常结束才能使用此宏。
WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为

WTERMSIG(status) 取得子进程因信号而中止的信号代码,一般
会先用WIFSIGNALED 来判断后才使用此宏。
WIFSTOPPED(status) 如果子进程处于暂停执行情况则此宏值为
真。一般只有使用WUNTRACED 时才会有此情况。
WSTOPSIG(status) 取得引发子进程暂停的信号代码,一般会先
用WIFSTOPPED 来判断后才使用此宏。
返回值
如果执行成功则返回子进程识别码(PID),如果有错误发生则返回
-1。失败原因存于errno 中。

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<sys/types.h>
void disp0();
void disp1();
void disp2();
int mymax(int ,int);
int main(void)
{
    pid_t child;
    int status,ans;
    void (*fun[3])();
    int (*pm)(int x,int y);
    int num1,num2,num3,max_num;
    fun[0]=disp0;
    fun[1]=disp1;
    fun[2]=disp2;
    pm=mymax;
    printf("是否复制进程?(1: yes,2:No)");
    scanf("%d",&ans);
    if(ans==1)
    {
        child=fork();
        if(child==-1)
        {
            perror("fork error");
            exit(1);
        }
    }
    if(child==0)
    {
        puts("这是子进程...");
        printf("\t 子进程 pid=%d\n",getpid());
        printf("\t 子进程ppid=%d \n",getppid());
        printf("要购买哪一种产品?(0:计算机 1:电视: 2:音箱)");
        scanf("%d",&num3);
        if(num3>=0&&num3<=2)
        {
            (*fun[num3])();
        }    exit(0);
    }
    else
    {
        waitpid(child,&status,0);
        puts("这是父进程....");
        printf(" \t 父进程 pid=%d\n",getpid());
        printf("\t 父进程 ppid=%d \n",getppid());
        printf("\t 子进程离开的状态: %d \n",WIFEXITED(status));
        printf("输入第一个数值:");
        scanf("%d",&num1);
        printf("输入第二个数值:");
        scanf("%d",&num2);
        printf("输入第三个数值:");
        scanf("%d",&num3);
        max_num=(*pm)(num1,num2);
        printf("最大值为 %d \n",max_num);
        exit(0);    
    }
    return 0;
}
int mymax(int x, int y)
{
    if(x>y)
        return x;
    else
        return y;
}
void disp0()
{
    printf("您购买了计算机\n");
}
void disp1()
{
    printf("您购买了电视\n");
}
void disp2()
{
    printf("您购买了音箱\n");
}