0
点赞
收藏
分享

微信扫一扫

wait和waitpid函数

女侠展昭 2022-03-30 阅读 28

一个进程在终止时会关闭所有文件描述符,释放在用户空间分配的内存,但它的PCB还保留着,内核在其中保存了一些信息:如果是正常终止则保存着退出状态,如果是异常终止则保存着导致该进程终止的信号是哪个。

父进程可以调用wait或waitpid获取这些信息,然后彻底清除掉这个进程。

#include <sys/types.h>

#include <sys/wait.h>

pid_t wait(int *status);

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

例如:一个进程的退出状态(比如:return 0;)可以在Shell中用特殊变量$?查看,因为Shell是它的父进程,当它终止时Shell调用wait或waitpid得到它的退出状态的同时彻底清除掉这个进程。

如果一个进程已经终止,但是它的父进程尚未调用wait或waitpid对它进行清理,这时的进程状态称为僵尸(Zombie)进程,可以用ps u查看进程状态。 

父进程调用wait或waitpid时可能会:

        1.阻塞(如果它的所有子进程都还在运行)。ps:Shell就是阻塞等着子进程运行完毕。

        2.带子进程的终止信息立即返回(如果一个子进程已终止,正等待父进程读取其终止信息)。

        3.出错立即返回(如果它没有任何子进程)。

wait和waitpid区别:

        如果父进程的所有子进程都还在运行,调用wait将使父进程阻塞,而在调用waitpid时如果在options参数中指定WNOHANG可以使父进程不阻塞而立即返回0。wait等待第一个终止的子进程,而waitpid可以通过pid参数指定等待哪一个子进程。

用waitpid函数获取子进程死亡原因: 

#include "./common/head.h"

/*功能:
 *用waitpid函数获取子进程死亡原因。
*/

int main()
{
    pid_t pid = fork();
    if(pid < 0){
        perror("fork");
        exit(1);
    }

    if(pid == 0){    //子进程
        int n = 5;
        while(n--){    //子进程5秒后结束
            printf("this is child process\n");
            sleep(1);
        }
        exit(3);    //父进程中打印正常退出代码为3
    }else{    //父进程
        int stat_val;
        //等待子进程退出
        wait(pid, &stat_val, 0);    //pid为-1时代表等待所有子进程结束,子进程结束的信息存储在stat_val中,可以用以下的宏来进行判断
        if(WIFEXITED(stat_val)){    //子进程正常退出
            //打印正常退出代码,即上面返回的3
            printf("Child exited with code %d\n", WEXITSTATUS(stat_val));
        }else if(WIFSIGNALED(stat_val)){    //子进程是被信号终止的
            //打印信号
            printf("Child terminated abnormally, signal %d\n", WTERMSIG(stat_val));
        }
    }

    return 0;
}
举报

相关推荐

0 条评论