僵尸进程,孤儿进程、守护进程以及wait函数,waitpid函数

僵尸进程

如果子进程退出,但是父进程没有调用 wait 或 waitpid 获取子进程的状态信息,那么子进程的进程描述符(task_struct)仍然保存在系统中,那么该子进程叫做僵尸进程

#include<iostream>
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<semaphore.h>
using namespace std;

int main()
{
    pid_t pid=fork();

    if(pid>0)
    {
        cout<<"in paraten process,sleep..."<<endl;
        sleep(3);
        cout<<"after sleep"<<endl;
    }
    else if(pid==0)
    {
        cout<<"in child process"<<endl;
        exit(0);
    }
    return 0;
}

父进程睡眠3s等待子进程结束,父进程没有调用函数等待子进程回城子进程的资源,所以子进程变成了一个僵尸进程

当这个父进程醒来然后也退出之后,该子进程就变成孤儿进程然后被 1 号 init 进程收养了,而 init 进程会周期性的调用 wait 函数来清除各个僵尸子进程


tip:fork() 只能在Linux中创建父子进程

#include<iostream>
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<semaphore.h>
#include<sys/wait.h>
#include<sys/types.h>
using namespace std;

int main()
{
    pid_t pid=fork();

    if(pid>0)
    {
        cout<<"in parate process"<<endl;
        pid_t pr=wait(NULL);
        cout<<"in parent process,I catched a child process with pid of "<<pid<<endl;
    }
    else if(pid==0)
    {
        cout<<"in child process,PID="<<getpid()<<" PPID:"<<getppid()<<endl;
        exit(0);
    }
    return 0;
}

wait函数的原理:进程调用wait,然后阻塞自己,然后寻找僵尸子进程,找到了则销毁子进程然后返回,没有找到则一直阻塞直到找打僵尸子进程为止

程序在1s内就结束了

wait函数原型

pid_t wait(int *status)

如果status的值不是NULL,wait就会把子进程退出时的状态码取出存入status中,这样我们可以知道子进程是正常退出还是非正常退出

需要注意的是,子进程状态信息被放在一个整数的不同二进制位中,所以有一个专门的宏macro来读取信息,比如WIFEXITED(status),子进程正常退出返回非0值,当子进程是正常退出时,我们可以使用WEXITSTATUS来获取子进程的返回值,比如子进程返回5,那么我们就可以获取这个返回值

利用宏获得子进程的返回值:

#include<iostream>
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<semaphore.h>
#include<sys/wait.h>
#include<sys/types.h>
using namespace std;

int main()
{
    pid_t pid=fork();

    if(pid<0)
    {
        cout<<"fork error"<<endl;
        return 0;
    }
    else if(pid>0)
    {
        cout<<"in parate process"<<endl;

        int status=-1;
        pid_t pr=wait(&status);

        if(WIFEXITED(status))
        {
            cout<<"the child process exit normal"<<endl;
            cout<<"the child return code is "<<WEXITSTATUS(status)<<endl;
        }
        else
        {
            cout<<"the child process exit  abnormal,pid="<<pr<<endl;
        }
    }
    else if(pid==0)
    {
        cout<<"in child process,PID="<<getpid()<<" PPID:"<<getppid()<<endl;
        exit(6);
    }
    return 0;
}

子进程返回6,父进程通过宏获得了子进程的返回值,需要注意的是:返回值有一定的大小,太大了不可以,因为整个整数的比特位存储的是子进程返回的一些信息,有位数限制

waitpid函数原型

pid waitpid(pid_t pid,int *status,int options)

pid参数:

1)  pid>0:只等待进程ID等于pid的子进程,不管其它已经有多少子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去
2)  pid=-1:等待任何一个子进程,没有限制,此时和wait函数作用一模一样
3)pid<-1:等待一个指定进程组中的任何子进程,进程组号=pid的绝对值
4)pid=0:等待一个指定进程组中的任何子进程,进程组号为pid的值

options参数:

1)  options=WNOHANG,即使子进程没有退出,它也会立即返回,不会像wait那样永远等下去
2)options=WUNTRECED,子进程睡眠则马上返回,但结束状态不予理会
3)options=0,不使用该参数

和wait函数相比,waitpid其实是wait函数的封装,waitpid可以指定等待的子进程,并且指定返回的条件

孤儿进程

父进程退出后,它的一个或多个子进程还在运行,那么这些子进程叫做孤儿进程

孤儿进程将会被1号进程init进程收养,并且由Init进程(pid = 1)完成对他们的状态收集工作

并由Init进程调用wait函数等待其结束,完成状态收集工作。孤儿进程并不会对系统造成危害

守护进程

守护进程(dameon)是运行在后台的一种特殊进程,不与任何终端相关联,关闭终端不会影响守护进程的生命周期,伴随系统启动和关闭,一直运行在后台。

守护进程通常以d结尾,比如数据库服务器mysqld、web服务器httpd、系统日志进程syslogd等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值