当前位置: 首页 > news >正文

Linux操作系统--进程等待

目录

1.进程等待的必要性

2进程等待的方法:

2.1wait方法

2.2waitpid方法

1.3获取子进程status

waitpid的使用


1.进程等待的必要性

之前在进程状态章节,我们讲过僵尸进程的危害。僵尸进程无法被杀死,需要通过进程等待来杀掉它,进而解决内存泄漏问题

我们通过进程进程等待,获得子进程的退出情况----父进程得知道自己布置给子进程的任务,它完成的怎么样了。

2进程等待的方法:

2.1wait方法

#include<sys/types.h>

#include<sys/wait.h>

pid_t wait(int *status);

返回值:成功返回被等待进程pid,失败返回-1

参数:输出型参数,获取子进程退出状态,不关心则可以设置成为NULL

2.2waitpid方法

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

返回值:

  当正常返回的时候waitpid返回收集到的子进程的进程ID;

  如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;

  如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;

参数:

        pid:
                Pid = -1,等待任一个子进程,与wait等效

                Pid>0,等待其进程id与pid相等的子进程。

        status:
                WIFEXITED(status):若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)

                WEXITSTATUS(status):若WIFEXITED非零,提取子进程退出码。(查看进程退出码)

        options:

                WNOHANG:若pid指定的子进程没有结束,则waitpid()函数返回0,不及以等待。若正常结束,则返回该子进程的ID。

  • 如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,并且释放资源,获得子进程退出信息
  • 如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞
  • 如果不存在该子进程,则立即出错返回

1.3获取子进程status

  • wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充
  • 如果传递NULL,表示不关心子进程的退出状态信息
  • 否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程
  • status不能简单的当作整型来看待,可以当作位图来看待

WIFEXITED 宏用于检测子进程是否正常退出

  • (status) 的最低八位 (&0xFF) 被检查。
  • 如果这八个比特全为零,则说明子进程是由于调用 exit() 正常结束的。

这意味着,如果子进程因接收到某种致命信号而被迫终止,那么这八个比特不会全部为零,从而使得 WIFEXITED 返回假值。

WEXITSTATUS 的工作原理

一旦确认子进程确实正常退出(即 WIFEXITED(status) 返回真),就可以使用 WEXITSTATUS 来获取实际的退出状态码。其典型定义如下:

这里的关键操作有两点:

  • 将整个 status 右移八位 (>> 8) ,以便丢弃低位上的标志比特;
  • 接着再次与 0xFF 执行按位 AND 操作,确保只保留高位中的有效退出码4

因此,最终的结果是从原始 status 值中抽取出来的真正的退出状态码

#include<sys/types.h>
#include<sys/wait.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
int main()
{pid_t pid = fork();if(pid == -1){perror("fork");exit(1);}if(pid == 0){sleep(20);exit(10);}else{int st;int ret = wait(&st);//0x7F转成二进制1111 111,因为子进程正常退出st的0-7比特位都是0//我们&0x7F是为了验证子进程是否正常退出if(ret > 0 && (st & 0x7F)==0){printf("child exit code:%d\n",(st>>8)&0xFF);}else if(ret > 0){printf("sig code: %d\n",st&0x7f);}}return 0;
}

如果直接杀掉进程:

waitpid的使用

进程阻塞等待方式:

#include<sys/types.h>
#include<sys/wait.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>int main()
{pid_t pid = fork();if(pid < 0){perror("fork");exit(1);}else if(pid == 0){printf("child is run, pid is : %d\n",getpid());sleep(5);exit(257);}else{int status = 0;pid_t ret = waitpid(-1,&status,0);printf("this is test for wait\n");if(WIFEXITED(status) && ret == pid)printf("wait child 5s success, child return code is :%d\n",WEXITSTATUS(status));else{printf("wait child failed,return\n");return 1;}}return 0;
}

进程的非阻塞等待方式:

#include<sys/types.h>
#include<sys/wait.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>int main()
{pid_t pid = fork();if(pid < 0){perror("fork");exit(1);}else if(pid == 0){printf("child is run, pid is : %d\n",getpid());sleep(5);exit(1);}else{int status = 0;pid_t ret = 0;do{ret = waitpid(-1,&status,WNOHANG);if(ret == 0)printf("child is running\n");sleep(1);} while(ret == 0);if(WIFEXITED(status) && ret == pid)printf("wait child 5s success, child return code is :%d\n",WEXITSTATUS(status));else{printf("wait child failed,return\n");return 1;}}return 0;
}

相关文章:

  • 【全网最全】23种设计模式思维导图详解 | 含React/Vue/Spring实战案例
  • JavaScript 闭包:从原理到实战应用
  • 单片机 + 图像处理芯片 + TFT彩屏 进度条控件
  • Nacos 客户端 SDK 的核心功能是什么?是如何与服务端通信的?
  • Qt界面控件中点击触发处理耗时业务的方法
  • 【MySQL】详细介绍(两万字)
  • 基于大模型的腹股沟疝全流程预测与诊疗方案研究报告
  • 掌握常见 HTTP 方法:GET、POST、PUT 到 CONNECT 全面梳理
  • Transformer中Post-Norm和Pre-Norm如何选择?
  • 影像数据处理
  • P5670 秘籍-反复异或 Solution
  • 日语学习-日语知识点小记-构建基础-JLPT-N4阶段(8): - (1)复习一些语法(2)「~ています」
  • C++中函数的实现写在头文件内
  • 第 6 篇:衡量预测好坏 - 评估指标
  • 机器视觉lcd屏增光片贴合应用
  • unity基础自学2.3:移动和抓握物品
  • Qt项目——汽车仪表盘
  • Git SSH 密钥多个 Git 来源
  • 研究夜间灯光数据在估计出行需求方面的潜力
  • MySQL 按照日期统计记录数量
  • “75后”遂宁市长刘会英调任四川省人社厅党组副书记
  • GDP增长4.1%,一季度广东经济数据出炉
  • 包邮到高原,跨越4083公里送妈妈一张按摩椅
  • 马上评|与其争论董宇辉该不该获奖,不如多关心文学
  • 中央和国家机关工委建立健全整治形式主义为基层减负长效机制
  • 首批换药患者已出现,两大减肥药巨头比拼的是什么?