news 2025/12/28 9:56:10

【Linux】进程控制(2)进程等待

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Linux】进程控制(2)进程等待

hello~ 很高兴见到大家! 这次带来的是Linux系统中关于进程控制这部分的一些知识点,如果对你有所帮助的话,可否留下你宝贵的三连呢?
个 人 主 页: 默|笙


文章目录

  • 一、进程等待
    • 1.1 进程等待的必要性
    • 1.2 进程等待的方法
      • 1. wait方法
      • 2. waitpid方法
        • 阻塞等待vs非阻塞等待
      • 3. 获取子进程status

接上次博客---->[进程控制(1)进程创建、终止]。


一、进程等待

1.1 进程等待的必要性

  1. 我们知道一个进程执行完了之后不会立即变成死亡状态,而是变成僵尸状态,如果这个进程的父进程对它不管不顾的话,那么它将一直存在于内存当中,占用系统内存也占用系统所分配的pid。
  2. 处于僵尸状态的进程是无法信号kill -9被杀死的,毕竟谁也无法杀死一个已经死掉的进程。
  3. 其次,父进程派给子进程执行的任务,任务完成的如何我们是需要知道的。比如子进程任务执行结果对不对,是不是正常终止,这部分退出信息是存储在它的task_struct里面。
  4. 既为了不让子进程一直处于僵尸状态(必须),也为了能够知道子进程任务完成的如何,我们需要让父进程对僵尸状态的子进程进行回收—回收子进程资源,获取子进程退出信息。
  • 退出信息储存在子进程的task_struct里面,,,,

1.2 进程等待的方法

1. wait方法

  1. 使用wait需要包含头文件sys/wait.h。
  2. 返回值:如果等待成功返回所等待的子进程的id,等待失败则返回-1。
  3. 关于参数stat_loc,这是一个输出型参数,用来获得子进程的状态,不关心则可以设置成NULL,之后会讲到。
  • 输出型参数:输出型参数的初始值并不重要,因为它是在调用函数后被函数赋值,成为一个函数执行结果的载体,可以通过这个参数获取结果,在这里就是子进程的退出状态。
#include<sys/wait.h>2#include<stdio.h>3#include<unistd.h>4#include<stdlib.h>56intmain()7{8pid_t id=fork();9if(id==0)10{11intcnt=5;12while(cnt--)13{14printf("我是一个子进程!pid:%d, ppid:%d\n",getpid(),getppid());15}16exit(0);//子进程执行完退出17}18sleep(10);19pid_t sid=wait(NULL);20if(sid>0)21{22printf("我是一个父进程!pid:%d,我等待成功了,回收的是pid为%d> 的子进程\n",getpid(),sid);23}24return0;25}


  1. 执行程序之后,子进程执行代码会通过exit终止进程进入僵尸状态,为了不让父进程一下子给子进程回收掉,我让程序sleep了10s,10s过后父进程回收子进程,子进程死亡,父进程执行完代码被bash直接回收,进入死亡状态。
  2. wait方法里:在子进程执行的过程中,父进程会一直处于阻塞状态,父进程会一直等待子进程的结束好对其进行回收,不会做其他的事情。如果想验证可以让子进程休眠5s,让子进程执行的时间久一点,可以观察到父子进程都处于S+状态。
  • wait是回收任意一个已退出处于僵尸状态的子进程,如果没有则为阻塞等待状态。

2. waitpid方法

  1. 同样需要包含头文件sys/wait.h进行使用,不过与wait不同的是,它多了两个参数,一个pid,一个options。

  2. 第一个参数pid是要传给它目标子进程pid,然后它就只会等这个目标子进程,如果想回收任意子进程,就传-1

  3. stat_loc也是输出型参数,用来获取子进程的退出信息。

  4. options默认值为0,表示阻塞等待,即父进程等待子进程的这段时间什么事情都不干,就干等。如果传入WNOHANG(wait no hang不等待),表示非阻塞等待,也就是在等待子进程的时间里面父进程可以干其他的事情

  5. 返回值:在阻塞状态下等待成功则返回所等待子进程的pid,等待失败则返回-1;在非阻塞状态下,如果子进程还没有执行完成则返回0,不继续等待,若正常结束,返回子进程pid。

  • 第一个参数为-1,第三个参数为0时,与wait函数功能相同。
阻塞等待vs非阻塞等待
  1. 打个比方,我烧一壶水,烧这一壶水是需要时间的,阻塞等待就是我一直在这里等着这壶水烧开,这段时间里我什么也不干,就在它旁边守着直到听到它发出咕噜咕噜的声音知道它烧开为止;非阻塞等待就是我在烧这壶水的期间去干其他事情,干一会儿就回来看看水烧开没有,这样既可以等待水的烧开又可以干自己的事情。
  2. 要注意的是,等待的时间是取决于子进程的,无论是阻塞等待还是非阻塞等待要等的时间都是一样的。不存在非阻塞等待比阻塞等待效率高的说法,只能说是非阻塞等待干其他事情的效率提高了
//非阻塞状态实验代码1#include<stdio.h>2#include<unistd.h>3#include<stdlib.h>4#include<sys/wait.h>56intmain()7{8pid_t id=fork();9if(id==0)10{11intcnt=5;12while(cnt--)13{14sleep(1);15printf("我是一个子进程,pid:%d, ppid: %d\n",getpid(),getppid());16}17exit(0);18}19while(1)20{21pid_t sid=waitpid(id,NULL,WNOHANG);22if(sid==0)23{24printf("我是父进程,子进程还没执行完,我要干我自己的事情了\n");25//写父进程等待期间要执行的代码26}27elseif(sid>0)28{29printf("我是父进程,我回收成功了!pid:%d\n",getpid());30exit(0);31}32}33return0;34}
  1. 执行非阻塞等待,第三个参数传入WNOHANG,父进程要使用一个while循环,去不断的使用waitpid()函数进行等待,如果返回值为0则干父进程自己的事情,返回值不为0就回收完毕,父进程终止。差不多就是下面的样子。

3. 获取子进程status

  1. wait函数和waitpid函数都有一个参数status,一个输出型参数,用来获得系统给的子进程的退出信息。
  2. 如果传递的是NULL,则默认不关心子进程的退出状态信息。如果传递的是一个整型变量,那么系统给的子进程的退出信息就会在调用wait/waitpid函数之后存储在这个整型变量里面。

  1. 系统给的退出信息不是一个简单的整数,应该把它当作位图来看待,一个整数4个字节是32bit位,但是退出信息只会存储在16个比特位里面,最高16位一般不会使用。
  2. 在这16个比特位里面,如果是正常终止,那么第8~15个比特位里面会存储子进程的退出状态(0~255),第7位则固定为0,第0~6位为未使用(全为0);如果是被信号所杀,那么第8~15位是没有使用的(全为0),第7位存储的是core dump标志,第0~6位存储的则是终止子进程的信号编号。
  3. 我们可以通过位运算来获取系统给的退出信息,也可以使用系统给的宏来获取:
  1. WIFEXITED(status): 若为正常终止进程返回的状态,则为真(1)。对应(status & 0x7F) == 0,如果信号为0,说明正常终止了。0x7F = 0111 1111。
  2. WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程
    的退出码)对应(status >> 8) & 0xFF,向左移动8位进行提取。0xFF = 1111 1111。
1#include<stdio.h>2#include<unistd.h>3#include<stdlib.h>4#include<sys/wait.h>56intmain()7{8pid_t id=fork();9if(id==0)10{11intcnt=5;12while(cnt--)13{14sleep(1);15printf("我是一个子进程,pid:%d, ppid: %d\n",getpid(),getppid());16}17exit(0);18}19while(1)20{21int*status=NULL;22pid_t sid=waitpid(id,status,WNOHANG);23if(sid==0)24{25// printf("我是父进程,子进程还没执行完,我要干我自己的事情了\n");26//写父进程等待期间要执行的代码27}28elseif(sid>0)29{30printf("我是父进程,我回收成功了!pid:%d\n",getpid());31printf("我是父进程,WIFEXITED:%d, WEXITSTATUS:%d\n",WIFEXITED(status),WEXITSTATUS(status));32exit(0);33}34}35return0;36}

  1. 正常终止,WIFEXITED返回值为1,WEXITSTATUS有意义,返回值为0,代表退出码为0,结果正确。

今天的分享就到此结束啦,如果对读者朋友们有所帮助的话,可否留下宝贵的三连呢~~
让我们共同努力, 一起走下去!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/26 4:02:35

计算机Java毕设实战-基于SpringBoot+Vue技术的医疗器械管理系统设计与实现基于springboot+vue小型医院医疗设备管理系统【完整源码+LW+部署说明+演示视频,全bao一条龙等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2025/12/26 0:05:55

千匠大宗电商系统:赋能煤炭能源行业产业升级

在全球能源结构转型与数字技术深度融合的时代背景下&#xff0c;能源煤炭行业正迎来一场深刻的供应链变革。传统交易模式中信息不对称、交易链条长、融资难、物流协同效率低等痛点&#xff0c;已成为制约行业高质量发展的关键瓶颈。千匠大宗电商系统致力于为煤炭能源大宗商品交…

作者头像 李华
网站建设 2025/12/26 6:32:07

硬件有限,如何部署“大”模型?AMCT模型压缩工具3步解忧

我们在谈论AI大模型时&#xff0c;一方面会为其在逻辑推理、问题回答等各种任务中的表现出色而惊叹&#xff0c;另一方面也会为其巨大存储和海量计算而“头疼”。模型尺寸的不断增长确实给模型部署带来了极大的挑战&#xff0c;动辄几十GB&#xff0c;上百GB甚至上千GB的存储量…

作者头像 李华
网站建设 2025/12/24 23:45:35

【毕业设计】基于SpringBoot+Vue技术的医院运营管理系统的设计与实现(源码+文档+远程调试,全bao定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2025/12/26 0:57:31

Java毕设选题推荐:基于SpringBoot的非遗产品交流销售平台的设计与实现基于springboot的非遗文化传承与推广平台系统【附源码、mysql、文档、调试+代码讲解+全bao等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2025/12/27 7:47:28

学长亲荐8个AI论文平台,本科生毕业论文轻松搞定!

学长亲荐8个AI论文平台&#xff0c;本科生毕业论文轻松搞定&#xff01; 论文写作的“隐形助手”&#xff1a;AI 工具如何改变你的毕业之路 在当今这个信息爆炸的时代&#xff0c;高校学生的论文写作压力与日俱增。无论是选题、大纲搭建&#xff0c;还是内容撰写和查重降重&…

作者头像 李华