• Linux系统编程-进程等待


    一. 进程退出的情况

    1.1 程序运行完毕

    结果正常: 默认情况下的退出码为0

    结果不正常: 默认退出的退出码为大于0的整数,每一个数字代表对应的情况

    补充:main函数返回,调用exit或者_exit,都可以获取进程的退出码。_exit是系统调用接口,不会清理文件缓冲区,关闭流。exit会清理缓冲区和关闭流。在命令行输入echo $?可以查看最近一次进程的退出码,在C程序调用strerror(i),会返回退出码i代表的含义

    1.2 程序异常终止

    接收到信号,被强制终止。在命令行执行kill -l可以查看有哪些终止的信号。

    二. 进程等待

    2.1 为什么需要等待

    1. 子进程退出,父进程没有进行等待,子进程就会变成僵尸进程,进而造成内存泄露。
    2. 父进程需要通过等待的方式去回收子进程的资源,获取子进程退出的信息。

    2.2 进程等待的方法

    2.21 wait方法

    在这里插入图片描述

    // 1. pid_t wait (int *status);
    // status是用来保存子进程退出的信息
    // 一共是32个比特位
    // 低7位用来存放终止信号,程序接收到异常信号就会被强制退出,正常退出终止信号位0
    // 低第9位到低第16位存放的是退出状态码,也就是exit,和return发送的退出码
    int main()
    {
        pid_t ret = fork();
    
        if (ret < 0)
        {
            perror("fork");
        }
        if (0 == ret)
        {
            // child
            int a = 5;
            a /= 0;
            while (a--)
            {
                printf("%d\n", a + 1);
                sleep(1);
            }
            exit(100);
        }
        // parent
        printf("wait begin\n");
        int status = 0;
        //pid_t id = wait(NULL);
        pid_t id = wait(&status);
        if (-1 == id)
        {
            printf("wait failed\n");
            exit(1);
        }
        printf("success, pid is %d\n", id);
        //printf("exit_code --> %d  :  signal --> %d\n", (status >> 8) & 0xff, status & 0x7f);
        // WIFEXITED(status),如果进程正常退出返回true
        if (WIFEXITED(status))
        {
            // WEXITSTATUS(status),返回进程的退出码,进程正常退出才会有效
            printf("eixt_code --> %d\n", WEXITSTATUS(status));
        }
        else
        {
            printf("A signal has been picked up\n");
            
            // WTERMSIG(status),返回终止进程的信号,进程被信号终止的情况下才会有效
            printf("signal --> %d\n", WTERMSIG(status));
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    2.22 waitpid方法

    // 2. pid_t waitpid(pid_t pid, int* status, int options);
    // pid 是需要等待的子进程的pid, 传-1过去表示等待任何一个子进程,也可以传具体等待的子进程pid
    // status 跟上面的一样
    // options 表示等待的方式,0为阻塞等待, WNOHANG为非阻塞等待
    int main()
    {
        pid_t ret = fork();
    
        if (ret < 0)
        {
            perror("fork");
        }
        if (0 == ret)
        {
            // child
            int a = 5;
            while (a--)
            {
                printf("%d\n", a + 1);
                sleep(1);
            }
            exit(0);
        }
        // parent
    
        // 阻塞等待
        /*
        printf("wait begin\n");
        //pid_t id = waitpid(-1, NULL, 0); 
        pid_t id = waitpid(ret, NULL, 0);
        if (-1 == id)
        {
            printf("wait failed\n");
            exit(1);
        }
        printf("success, pid is %d\n", id);
       	*/
        printf("wait begin\n");
        while (1)
        {
            // 非阻塞等待
            pid_t id = waitpid(ret, NULL, WNOHANG);
            if (-1 == id)
            {
                printf("wait failed\n");
                break;
            }
            else if (0 == id)
            {
                printf("do my thing\n");
            }
            else
            {
                printf("success! The child process has exited\n");
                break;
            }
            sleep(1);
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
  • 相关阅读:
    webpack 原理
    反射及暴力反射
    家政服务APP
    spyder切换conda环境(成功测试)
    svn co 大型项目
    探究——C# .net 代码混淆/加壳
    苹果MAC m1芯片安装Jdk、Maven
    C语言实现贪吃蛇[内附详细步骤]
    一、CC2530开发环境搭建
    【c++智能指针】模拟带有weak_ptr的shared_ptr
  • 原文地址:https://blog.csdn.net/Yohe1937/article/details/125547839