0

0

初识Linux · 进程等待

雪夜

雪夜

发布时间:2025-06-20 14:30:32

|

781人浏览过

|

来源于php中文网

原创

前言:

通过前文的学习,我们已经了解了进程终止的概念,包括终止的三种情况以及退出码和错误码的使用。对于退出码,我们知道可以通过echo $?来查看,并了解了如何终止进程。

本文将深入探讨进程等待,从三个方面进行分析:进程等待是什么?为什么需要等待?等待时在做什么?通过这三个方面的学习,相信同学们将对Linux中的进程等待有更深刻的理解。

进程等待是什么思考:在什么情况下会发生等待的情况?

情况实例:当父进程创建了子进程,而父进程任务结束时,子进程尚未结束,父进程需要等待子进程退出。这种情况就是等待。

那么,如果父进程不等待,直接退出,会引发什么后果呢?

如果父进程不等待,直接退出,那么子进程会变成僵尸进程,导致的问题包括内存泄漏,这是一个非常危险的问题。因此,通常情况下,父进程需要等待子进程退出。

以bash为例,如果我们执行的所有指令和可执行文件bash都不回收,那么内存将一次性耗尽,我们的机器很快就会报废。

因此,我们得出结论:

进程等待是指父进程在完成自己的任务后,为了系统的稳定性,需要等待子进程退出。

为什么需要进程等待除了考虑内存泄漏引发的安全问题,父进程还需要考虑获取子进程的退出信息,这是一个可选的选项,因为不是所有的子进程都需要父进程获取退出信息。

进程等待都在做什么前面两点,即便是没有学习过进程等待的同学也应该有所了解。今天的重点实际上是在等待子进程时,父进程在做什么。

为了介绍父进程等待时在做什么,我们不妨从一个函数开始——waitpid:

初识Linux · 进程等待从man 2号手册我们可以看到,waitpid的头文件是sys/types.h和sys/wait.h。其实,到现在为止,一个函数需要两个头文件我们已经见怪不怪了,比如fork函数,除了types还需要unistd头文件,这也可以说是一种学习的里程碑。

那么,参数方面,一共有三个:

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

这三个参数分别是:pid,即父进程要等待的子进程的pid,因为一个父进程可能创建多个子进程,需要指定等待哪个子进程;第二个参数是输出型参数,可能直接这么说我们不好理解,看这段代码就知道了:

int a = 0;scanf("%d",&a);

scanf的参数就是输出型参数,即不是给OS的,是给用户看的。第三个参数就像ls -a -l -n,这么多选项一样。

这里还有一个点,如果我们将pid参数设置为-1会怎么样呢?——等待的就是任意进程了。

初识Linux · 进程等待对于返回值,我们简单先理解为如果等待成功,返回的就是子进程的pid,否则返回-1:

代码为:

#include 
#include 
#include 
#include 
#include 
void ChildRun(){
    //int *p = NULL;
    int cnt = 5;
    while(cnt)
    {
        printf("I am child process, pid: %d, ppid:%d, cnt: %d\n", getpid(), getppid(), cnt);
        sleep(1);
        cnt--;
        //*p = 100;
    }
}
int main(){
    printf("I am father, pid: %d, ppid:%d\n", getpid(), getppid());
    pid_t id = fork();
    if(id == 0)
    {
        // child
        ChildRun();
        printf("child quit ...\n");
        exit(123);
    }
    sleep(7);
    // fahter
    //pid_t rid = wait(NULL);
    int status = 0;
    pid_t rid = waitpid(id, &status, 0);
    if(rid > 0)
    {
        printf("wait success, rid: %d\n", rid);
    }
    else
    {
        printf("wait failed !\n");
    }
    sleep(3);
    printf("father quit, status: %d, child quit code : %d, child quit signal: %d\n", status, (status>>8)&0xFF, status & 0x7F);
    return 0;
}




初识Linux · 进程等待当然了,对于waitpid我们应该先了解一下wait:

初识Linux · 进程等待wait其实就一个输出型参数,所以,如果输出型参数设置为NULL,就是代表不关心这个子进程,也就没了。因此,我们了解了waitpid之后,自然就了解了wait。waitpid的参数设置为-1也就和wait等效了。

对于正常来说,子进程进入了一个函数,通过cnt进行计时,5秒之后,子进程结束了,变成了僵尸,父进程还没有结束,父进程sleep一过开始回收,此时就回收成功:

初识Linux · 进程等待我们通过指令:

Notion AI
Notion AI

Notion是一款集成了笔记、知识库、数据表格、看板、日历等多种能力于一体的应用程序,它既可供个人使用,也可以与他人进行跨平台协作。

下载
while :; do ps -xaj | head -1 && ps -xaj | grep main | grep -v grep; sleep 1;done

就可以亲眼看到进程从僵尸状态变成了正常状态。

此时,细心的同学发现了最后打印的时候,打印了子进程的退出码,以及一个信号码:

初识Linux · 进程等待那么因为这里都是正常退出的,所以退出码我们自己设置的是123,所以打印出来也是123,至于有什么含义呢,我们自己规定即可。对于信号码来说,我们需要了解一个点:

退出信息的本质是什么?

退出信息本质上是一块有16bit位的空间,0 - 7bit位代表的是信号,8 - 15bit位代表的是退出码,退出信息实际上等于退出码 + 信号码,退出信息里面的core dump我们暂且不考虑,我们需要知道退出码从哪里看?

你看代码,代码打印退出码,打印信息码的时候,我们是不是通过按位与操作获取了某个特定区域的bit位并且打印出来了。那个操作实际上就是代表的取退出码和取信号码。

那么你是否会觉得退出码和信号码为什么只需要这么多个?

我们可以看:

初识Linux · 进程等待拿信号举例,一共就那么多,7个bit位还多了呢,退出码同理可得即可。

那么这里我们注意一下,11号信号是段错误,我们如果让子进程发生越界访问:

初识Linux · 进程等待也就是这里让空指针修改一下:

初识Linux · 进程等待可以看到退出码为0,可是我们知道如果发生了越界,进程终止实际上是被信号所杀,退出码实际上是没有用处的,这里的信号码为11,我们就知道了,是OS给子进程发送了11号信号,从而导致了子进程终止,但是父进程正常等待是成功了的。

父进程等待的时候,就一点事儿都不做吗?

不完全是的,父进程等待的时候分为两种等待,一种是阻塞等待,一种是非阻塞等待。对于阻塞等待,就像scanf,输入数据之后,需要等待键盘数据就绪,这是一种阻塞,而子进程本质也是软件,父进程实际上就是等待该软件就绪,也就是啥也不干,就等着呗。

这是阻塞等待。

那么非阻塞等待就需要借助我们的WNOHANG,也就是第三个参数。

此时是非阻塞等待,那么父进程一般要做的就是边做自己的事,通过循环,每过一段时间就问子进程是否结束没有,此时这个过程:非阻塞等待 + 循环 = 非阻塞轮询。

至于等待的三种情况,等待成功,pid_t返回的值是大于0,==0代表的是等待成功,但是子进程正准备结束了,

那么如果子进程是个死循环父进程一直等待不了怎么办,这就是OS的事儿了。

非阻塞呢,就是将第三个参数设置为WNOHANG即可。

感谢阅读!

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

232

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

437

2024.03.01

空指针异常处理
空指针异常处理

本专题整合了空指针异常解决方法,阅读专题下面的文章了解更多详细内容。

22

2025.11.16

磁盘配额是什么
磁盘配额是什么

磁盘配额是计算机中指定磁盘的储存限制,就是管理员可以为用户所能使用的磁盘空间进行配额限制,每一用户只能使用最大配额范围内的磁盘空间。php中文网为大家提供各种磁盘配额相关的内容,教程,供大家免费下载安装。

1350

2023.06.21

如何安装LINUX
如何安装LINUX

本站专题提供如何安装LINUX的相关教程文章,还有相关的下载、课程,大家可以免费体验。

704

2023.06.29

linux find
linux find

find是linux命令,它将档案系统内符合 expression 的档案列出来。可以指要档案的名称、类别、时间、大小、权限等不同资讯的组合,只有完全相符的才会被列出来。find根据下列规则判断 path 和 expression,在命令列上第一个 - ( ) , ! 之前的部分为 path,之后的是 expression。还有指DOS 命令 find,Excel 函数 find等。本站专题提供linux find相关教程文章,还有相关

294

2023.06.30

linux修改文件名
linux修改文件名

本专题为大家提供linux修改文件名相关的文章,这些文章可以帮助用户快速轻松地完成文件名的修改工作,大家可以免费体验。

776

2023.07.05

linux系统安装教程
linux系统安装教程

linux系统是一种可以免费使用,自由传播,多用户、多任务、多线程、多CPU的操作系统。本专题提供linux系统安装教程相关的文章,大家可以免费体验。

573

2023.07.06

Python GraphQL API 开发实战
Python GraphQL API 开发实战

本专题系统讲解 Python 在 GraphQL API 开发中的实际应用,涵盖 GraphQL 基础概念、Schema 设计、Query 与 Mutation 实现、权限控制、分页与性能优化,以及与现有 REST 服务和数据库的整合方式。通过完整示例,帮助学习者掌握 使用 Python 构建高扩展性、前后端协作友好的 GraphQL 接口服务,适用于中大型应用与复杂数据查询场景。

1

2026.01.21

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
CSS3 教程
CSS3 教程

共18课时 | 4.7万人学习

PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.5万人学习

Git 教程
Git 教程

共21课时 | 2.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号