C语言从零开始——wait和waitpid

####   wait函数   ####

wait函数只是针对一个子进程情况,查看man手册wait用法:pid_t wait(int *status);

参数是int*类型,返回值是pid_t类型;

wait执行原理:

1,子进程先结束,会发一个信号SIGCHLD

2,父进程调用wait等待子进程结束,再执行父进程下来的代码;如果子进程没有结束,就一直在等,会阻塞。

3,有资源回收函数,信号发给父进程,此时就可以回收(僵尸进程),父进程可以及时回收资源。没有资源回收函数,什么时候回收资源,父进程安排,通信是异步通信的。

4,如果父进程没有子进程,wait返回值错误。

演示代码:

#include 
#include 
#include 
/*
        wait对父子进程的影响:使得父进程处于阻塞状态,一直等待资子进程结束,wait结束,再去执行父进程
*/
int main()
{
        pid_t pid;
        int status = 1;
        pid = fork();

        if (pid > 0)
        {
                printf("father process :\n");
                wait(&status);//父进程执行到此,会停止,处于wait状态,等待子进程执行结束,然后父进程才会再执行
                printf("father process end : \n");
                exit(0);//每当一个进程执行结束,最好使用exit将其退出
        }
        else if (0 == pid)
        {
                printf("son process : \n");
                exit(0);
        }
        else
        {
                perror("fork");
                exit(0);
        }
        return 0;
}
执行结果:

表明:程序先进入父进程执行输出father process;然后发现wait函数,去执行子进程,输出son process,子进程结束后,父进程再重新继续执行

演示代码:(如果子进程不结束,父进程wait一直会阻塞)

#include 
#include 
#include 

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

        if (pid > 0)
        {
                printf("father process :\n");
                wait(&status);
                printf("father process end : \n");
                exit(0);
        }
        else if (0 == pid)
        while(1)  //当父进程执行到wait时,开始执行子进程,如果子进程死循环,则父进程会永远阻塞下去
        {
                sleep(1);
                printf("son process : \n");
        }
        else
        {
                perror("fork");
                exit(0);
        }
        return 0;
}
输出结果:

father process :
son process :
son process :
son process :
son process :
^C
最后强制退出;子进程死循环,父进程就一直wait阻塞。


####   wait测试状态   ####

wait函数中测试父进程是否正常退出,父进程是否由外界信号中断,以及子进程返回值的三个状态:
        WIFEXITED测试进程是否是正常退出:逻辑值(真或假)
        WEXITSTATUS测试你的子进程结束时的返回值(正常终止)
        WIFSIGNALED测试你的子进程是否时被外界信号终止(非正常终止)

演示代码:

#include 
#include 
#include 

int main()
{
        pid_t pid ,child_pid;
        int status = 1;
        pid = fork();

        if (pid > 0)
        {
                sleep(1);
                printf("father process : \n");
                child_pid = wait(&status);
//              printf("process end normally = %d \n",WIFEXITED(status));
                //如果父进程处于wait状态,WIFEXITED测试是否正常退出,输出为逻辑>值,若果正常退出,则输出1;否则为0

                printf("process end & test son process return vealue = %d \n",WEXITSTATUS(status));
                //测试子进程结束时的返回值(正常终止)

                printf("process end ennormally = %d \n",WIFSIGNALED(status));
                //测试父进程是否被外界信号中断,(非正常终止)
                printf("father process end;\n");
        }
        else if (0 == pid)
        {
                printf("son process : \n");
                sleep(1);
                return 3;
        }
        else
        {
                perror("fork");
                exit(0);
        }
        return 0;
}

演示结果:

son process :
father process :
process end & test son process return vealue = 3
process end ennormally = 0
father process end;

#### waitpid函数   ####

/*
        waitpid函数可以让父进程等待指定的pid
        用法:
        pid_t waitpid(pid_t pid, int *status, int options);
        waitpid(-1,int *status,int options); 如果为-1表示等待任意子进程
        pid_t pid的取值:
        < -1   meaning wait for any child process whose  process  group  ID  is
              equal to the absolute value of pid.取该pid的绝对值,如果任意子进程的进程组ID等于该绝对值,则该组进程中任一子进程中的进程状态发生变化都会触发waitpid()的回调。
       -1     meaning wait for any child process.监听范围扩大到任意子进程。
       0      meaning  wait  for  any  child process whose process group ID is
              equal to that of the calling process.监听限制为子进程的进程组ID与父进程相等。
       > 0    meaning wait for the child whose process  ID  is  equal  to  the
              value of pid.监听限制为指定子进程进程ID值。
*/
演示代码:

#include 
#include 
#include 

int main()
{
        pid_t pid,child_pid;
        int status = 1;

        pid = fork();

        if (pid > 0)
        {
                sleep(1);
                printf("father process ; \n");
//              child_pid = waitpid(-1,&status,0); //&status值可以为NULL当不为NULL时,用于存储触发状态变化的信息号值和exit(code)的code值
                //等待任意子进程pid

//              child_pid = waitpid(pid,&status,0);
                //等待指定子进程pid

                child_pid = waitpid(pid+1,&status,0);
                //如果等待一个不存在的子进程pid,阻塞的父进程就不会阻塞,运行返回值-1,继续执行父进程代码
                printf("child_pid = %d \n",child_pid);
                printf("father process end;\n");
        }
        else if (0 == pid)
        {
                printf("son process ; \n");
        }
        else
        {
                perror("fork");
                exit(0);
        }

        return 0;
}
输出结果:

son process ;
father process ;
child_pid = -1
father process end;


####   waitpid第三个参数   ####

/*
        pid_t waitpid(pid_t pid, int *status, int options);
        waitpid第三个参数:
        0:返回wait的进程的pid
        WNOHANG:如果子进程不存在就立即返回
        WUNTRACED
        WCONTINUED
        
*/

演示代码:

#include 
#include 
#include 
#include 
#include 
int main()
{
        pid_t pid,child_pid;
        int status = 1;

        pid = fork();
        if (pid > 0)
        {
                sleep(1);
                printf("father process ;\n");

//              child_pid = waitpid(pid,&status,WNOHANG);
                //WNOHANG如果子进程不存在就立即返回     

                child_pid = waitpid(pid,&status,0);
                //0返回wait的子进程的pid
                printf("son process pid = %d \n",child_pid);
                printf("father process end;\n");
        }
        else if (0 == pid)
        {

                printf("son process pid in son process = %d \n",getpid());
        }
        else
        {
                perror("fork");
                exit(0);
        }
        return 0;
}





你可能感兴趣的:(C&&C++)