Linux进程控制——进程等待

文章目录

进程等待

进程等待的过程其实是父进程等待子进程死亡的过程

进程等待的必要性

如果子进程退出,父进程不进行处理,子进程会变成僵尸进程,有内存泄漏的风险

僵尸进程只有父进程有权处理,其他指令对其都没有效果了

父进程创建子进程是为了完成某项任务,当子进程结束后,父进程有必要了解任务完成的如何

父进程需要对子进程进行回收

进程等待的方法

waitpid系统调用的返回值是pid_t,如果等待成功则返回进程pid,失败则返回-1

这个函数有三个参数,第一个参数是pid_t pid,表示需要等待的进程id,输入-1表示等待任一子进程结束

第二个参数是int* stat_loc,这是一个输出型参数,采用指针的方法获取子进程退出状态,如果我们不关心这个状态直接传入NULL即可

第三个参数是int options,默认为0,代表阻塞等待,也有非阻塞等待的情况

还有一个wait的系统调用,只有第二个参数,就相当于waitpid的默认使用情况

c 复制代码
#include<sys/wait.h>
#include<stdlib.h>
#include<stdio.h>

int main()
{
    pid_t id = fork();
    if(id==0)
    {
        int count = 5;
        while(count)
        {
            printf("%d: 这是一个子进程,pid为:%d\n", count, getpid());
            count--;
            sleep(1);
        }
        exit(0);
    }
    waitpid(id,NULL,0);
    printf("等待子进程\n");
    return 0;
}

我们知道的是,当子进程创建出来之后,父进程是不会进入到判断语句中的,而且也没有打印等待子进程,而是一直在执行waitpid这一行,是一直等到子进程执行完毕之后才继续执行的

status参数

父进程想要了解子进程的退出码和推出信号就需要用到这个输出型参数status

而退出码和退出信号是两个数据,怎么只用一个参数来表示,这其实就用到了位图的思想,用低八位表示异常终止的信号,剩下八位表示退出的状态

画出来就是这样的

终止信号的最高位是一个core dump标志,我们暂时先不研究

因此我们就可以通过位运算来获取退出码和终止信号

退出码是(status >> 8) & 0xFF

终止信号是status & 0x7F

我们可以手动设置一下退出码来进行验证

c 复制代码
#include<sys/wait.h>
#include<stdlib.h>
#include<stdio.h>

int main()
{
    pid_t id = fork();
    int status = 0;
    if(id==0)
    {
        int count = 5;
        while(count)
        {
            printf("%d: 这是一个子进程,pid为:%d\n", count, getpid());
            count--;
            sleep(1);
        }
        exit(21);
    }
    waitpid(id,&status,0);
    printf("等待子进程\n");
    printf("退出码:%d; 终止信号:%d\n",(status>>8)&0xFF),status&0x7F;
    return 0;
}

option参数

option参数的默认值为0,表示阻塞等待,就是说父进程啥也不干,就等着子进程结束,那如果想让父进程可以在等待的时候做自己的事情,就需要用一个宏定义WNOHANG

意思是 waiting no hang 父进程会继续运行下面的代码,因为waitpid的返回值是进程退出的pid,我们也就可以用这个来判断,子进程是否结束

然后写一个循环访问即可

例如

c 复制代码
#include<sys/wait.h>
#include<stdlib.h>
#include<stdio.h>

int main()
{
    pid_t id = fork();
    if(id==0)
    {
        int count = 5;
        while(count)
        {
            printf("%d: 这是一个子进程,pid为:%d\n", count, getpid());
            count--;
            sleep(1);
        }
        exit(21);
    }
    while(1)
    {
        int wait = waitpid(id,NULL,WNOHANG);
        if(wait==id)
        {
            printf("子进程退出,id为%d\n",wait);
            break;
        }
        else if(wait==0)
        {
            printf("子进程未退出\n");
        }
        else
        {
            perror("waitpid");
            exit(1);
        }
        sleep(1);
    }
    return 0;
}
相关推荐
ICscholar4 小时前
ExaDigiT/RAPS
linux·服务器·ubuntu·系统架构·运维开发
sim20205 小时前
systemctl isolate graphical.target命令不能随便敲
linux·mysql
薛定谔的猫19825 小时前
RAG(二)基于 LangChain+FAISS + 通义千问搭建轻量级 RAG 检索增强生成系统
运维·服务器·langchain
米高梅狮子5 小时前
4. Linux 进程调度管理
linux·运维·服务器
再创世纪6 小时前
让USB打印机变网络打印机,秀才USB打印服务器
linux·运维·网络
fengyehongWorld7 小时前
Linux ssh端口转发
linux·ssh
知识分享小能手8 小时前
Ubuntu入门学习教程,从入门到精通, Ubuntu 22.04中的Shell编程详细知识点(含案例代码)(17)
linux·学习·ubuntu
浩子智控9 小时前
电子产品设计企业知识管理
运维·服务器·eclipse·系统安全·硬件工程
以太浮标9 小时前
华为eNSP模拟器综合实验之-BGP路由协议的配置解析
服务器·开发语言·php
Xの哲學9 小时前
深入解析 Linux systemd: 现代初始化系统的设计与实现
linux·服务器·网络·算法·边缘计算