Linux进程等待

 

                                                         🎬慕斯主页修仙—别有洞天 

                                                         ♈️今日夜电波:HEART BEAT—YOASOBI

                                                                2:20━━━━━━️💟──────── 5:35
                                                                    🔄   ◀️   ⏸   ▶️    ☰  

                                      💗关注👍点赞🙌收藏您的每一次鼓励都是对我莫大的支持😍


 

目录

什么是进程等待?

进程等待必要性

进程如何等待?

wait方法

waitpid方法

返回值

参数status

WEXITSTATUS

附加option选项


什么是进程等待?

        进程等待是一种操作系统中的机制,它存在于父进程与子进程之间的关系。在一个进程创建了新的子进程后,这个父进程可能会需要等待子进程的完成,以收集子进程的资源和退出状态。

        在Linux系统中,wait函数和waitpid函数是用于实现进程等待的系统调用方法。wait函数会暂停当前进程的执行,直到一个子进程终止。当子进程终止后,wait函数会返回子进程的进程ID(PID),并将子进程的终止状态存储在指针status指向的变量中。

 

进程等待必要性

        之前的文章讲过,子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存泄漏。另外,进程一旦变成僵尸状态,那就刀枪不入,“杀人不眨眼”的kill -9 也无能为力,因为谁也没有办法杀死一个已经死去的进程。最后,父进程派给子进程的任务完成的如何,我们需要知道。如,子进程运行完成,结果对还是不对,或者是否正常退出。父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息。

进程如何等待?

wait方法

#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status);
返回值:
成功返回被等待进程pid,失败返回-1。
参数:
输出型参数,获取子进程退出状态,不关心则可以设置成为NULL

        进程等待回收子进程僵尸状态,这个状态的形成还是主要因为执行父进程代码前加了睡眠的状态,否则在子进程退出的一瞬间,父进程就已经回收完资源了,我们是看不到僵死进程的:

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <stdlib.h>
  4 #include <sys/types.h>
  5 #include <sys/wait.h>
  6 
  7 //int status = 0;
  8 void Worker(int number)
  9 {
 10     int cnt = 5;
 11     while(cnt)
 12     {
 13         printf("I am child process, pid: %d, ppid: %d, cnt: %d, number: %d\n", getpid(), getppid()    , cnt--, number);
 14         sleep(1);
 15 
 16         //*p = 100;
 17         //int a = 10;
 18         //a /= 0;
 19     }
 20     exit(0);
 21 }                                                                              
 22                                                         
 23 int main()                      
 24 {                  
 25   pid_t id=fork();                                         
 26   if(id==0)                          
 27   {                  
 28     Worker(1);                          
 29   }else{               
 30     sleep(7);                                                                                     
 31     pid_t rid=wait(NULL);                                          
 32     if(rid==id)                                                  
 33     {                                                     
 34       printf("i am father process,pid:%d,ppid:%d rid: %d\n",getpid(),getppid(),rid);
 35     }                                               
 36   }                                           
 37   return 0;
 38 }    

        进程等待,父进程必须在wait上进行阻塞等待,直到子进程僵尸状态,wait自动回收,因此父进程一般是最后退出的!

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <stdlib.h>
  4 #include <sys/types.h>
  5 #include <sys/wait.h>
  6 
  7 //int status = 0;
  8 void Worker(int number)
  9 {
 10     int cnt = 5;
 11     while(cnt)
 12     {                                                                                             
 13         printf("I am child process, pid: %d, ppid: %d, cnt: %d, number: %d\n", getpid(), getppid()    , cnt--, number);
 14         sleep(1);
 15 
 16         //*p = 100;
 17         //int a = 10;
 18         //a /= 0;
 19     }
 20     exit(0);
 21 }                                                                              
 22                                                         
 23 int main()                      
 24 {                  
 25   pid_t id=fork();                                         
 26   if(id==0)                          
 27   {                  
 28     Worker(1);                          
 29   }else{               
 30     pid_t rid=wait(NULL);
 31     if(rid==id)                                                    
 32     {                                                            
 33       printf("i am father process,pid:%d,ppid:%d rid: %d\n",getpid(),getppid(),rid);
 34     }                                 
 35   }                                                 
 36   return 0;                                   
 37 }

waitpid方法

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

参数:
pid:
Pid=-1,等待任一个子进程。与wait等效。
Pid>0.等待其进程ID与pid相等的子进程。
status:
WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
options:
WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进
程的ID。
返回值

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

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

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

参数status

        参数status是一个指向整数的指针,用于保存被收集子进程的退出状态。他32bit,其中低16位为中储存着数据。需要注意的是status不能简单的当作整形来看待,可以当作位图来看待。他的返回值实际上如下图所示:

        对此,如果我们要读取正确的信息,需要将status右移动8位。需要注意的是:如果进程被杀死了,如上图所示,status是无意义的!

  1 #include <sys/wait.h>
  2 #include <stdio.h>
  3 #include<unistd.h>
  4 #include <stdlib.h>
  5 #include <string.h>
  6 #include <errno.h>
  7 int main( void )
  8 {
  9 pid_t pid;
 10 if ( (pid=fork()) == -1 )
 11 perror("fork"),exit(1);
 12 if ( pid == 0 ){
 13 int ct=5;
 14 while(ct--)
 15 {
 16   printf("i am a child process times:%d,pid:%d,ppid:%d\n",ct,getpid(),getppid());
 17   sleep(1);
 18 }
 19 sleep(5);                                                                              
 20 exit(11);
 21 } else {
 22 int st;
 23 int ret = waitpid(pid,&st,0);
 24 if ( ret > 0 && ( st & 0X7F ) == 0 ){ // 正常退出
 25 printf("child exit code:%d\n", (st>>8)&0XFF);
 26 } else if( ret > 0 ) { // 异常退出
 27 printf("sig code : %d\n", st&0X7F );
 28 }
 29 }
 30 }

        正常退出情况:

        非正常退出,被进程杀死情况,此时为进程的信号量:

WEXITSTATUS

        WEXITSTATUS是一个宏,用于获取父进程中由子进程返回的退出状态。在C语言中,当一个进程通过调用exit()函数或_exit()函数来终止时,它会向其父进程返回一个整数值作为退出状态。

        WEXITSTATUS宏定义如下:

#define WEXITSTATUS(status) ((unsigned int)(status) >> 8)

        其中,status是子进程返回的退出状态。该宏将退出状态右移8位,以获取实际的退出状态值。

        使用WEXITSTATUS宏可以方便地获取子进程的退出状态,以便在父进程中进行进一步的处理或判断。

附加option选项
  1. WNOHANG:如果设置了这个选项,那么即使有子进程没有结束,waitpid也会立即返回,不会阻塞父进程。此时,waitpid函数会返回0,表示没有子进程已经结束。如果没有设置WNOHANG选项,那么waitpid会一直阻塞父进程,直到有一个子进程结束为止。
  2. WUNTRACED:如果设置了这个选项,那么即使子进程处于暂停状态(被暂停、停止或跟踪),waitpid也会返回。如果没有设置WUNTRACED选项,那么只有当子进程正常结束时,waitpid才会返回。
  3. WSTOPPED:如果设置了这个选项,那么只有当子进程处于暂停状态时,waitpid才会返回。如果没有设置WSTOPPED选项,那么只有当子进程正常结束时,waitpid才会返回。
  4. WCONTINUED:如果设置了这个选项,那么只有当子进程从暂停状态中恢复运行时,waitpid才会返回。如果没有设置WCONTINUED选项,那么只有当子进程正常结束时,waitpid才会返回。

        进程阻塞等待方式:

#include <sys/wait.h>
#include <stdio.h>
#include<unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main()
{
pid_t pid;
pid = fork();
if(pid < 0){
printf("%s fork error\n",__FUNCTION__);
return 1;
} else if( pid == 0 ){ //child
printf("child is run, pid is : %d\n",getpid());
sleep(5);
exit(257);
} else{
int status = 0;
pid_t ret = waitpid(-1, &status, 0);//阻塞式等待,等待5S
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 <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
pid_t pid;
pid = fork();
if(pid < 0){
printf("%s fork error\n",__FUNCTION__);
return 1;
}else if( pid == 0 ){ //child
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;
}

 


                       感谢你耐心的看到这里ღ( ´・ᴗ・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o! 

                                       

                                                                        给个三连再走嘛~  

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/293551.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

springboot中引入AOP切面编程

在Spring Boot 3.0中引入AOP的过程如下所示&#xff1a; 1、首先&#xff0c;确保已经添加了相关依赖。可以通过Maven或Gradle来管理项目的依赖。对于使用Maven构建的项目&#xff0c;需要将以下依赖添加到pom.xml文件中 <dependency><groupId>org.springframewo…

Sqlmap参数设置

Sqlmap参数设置 &#x1f388;&#x1f388;&#x1f388;&#x1f388;&#x1f388;&#x1f388;&#x1f388;&#x1f388;&#x1f388;&#x1f388;&#x1f388;&#x1f388;&#x1f388;&#x1f388; --------------------------------------------注意---------…

潜力快刊 | 新晋中科院1区TOP,Elsevier出版社,仅1个月Accept!审稿超快!稳定扩刊中!

【SciencePub学术】本期&#xff0c;小编给大家推荐的是一本Elsevier旗下新晋中科院1区TOP综合性期刊。其详情如下&#xff1a; 期刊简介 JOURNAL OF ADVANCED RESEARCH ISSN&#xff1a;2090-1232 E-ISSN&#xff1a;2090-1224 IF&#xff08;2022&#xff09;&#x…

SurfaceView和TextureView理解相关

一、为什么要使用SurfaceView 我们知道View是通过刷新来重绘视图&#xff0c;系统通过发出VSSYNC信号来进行屏幕的重绘&#xff0c;刷新的时间间隔是16ms,如果我们可以在16ms以内将绘制工作完成&#xff0c;则没有任何问题&#xff0c;如果我们绘制过程逻辑很复杂&#xff0c;…

unity C#中Array、Stack、Queue、Dictionary、HashSet优缺点和使用场景总结

文章目录 数组 (Array)列表 (List<T>)栈 (Stack<T>)队列 (Queue<T>)链表 (LinkedList<T>)哈希表 (Dictionary<TKey, TValue>) 或 HashSet<T>集合 (Collection<T>) 数组 (Array) 优点&#xff1a; 高效访问&#xff1a;通过索引可以…

自动生成表结构screw

采用的组件 screw 操作流程&#xff1a; 1、新建springboot 项目 2、引入相关的依赖 <!-- screw核心 --><dependency><groupId>cn.smallbun.screw</groupId><artifactId>screw-core</artifactId><version>1.0.4</version><…

从古代到现代:现代气体检测发展及其方法探究

在人类的发展历程中&#xff0c;气体检测一直是一个关键的领域。无论是古代还是现代&#xff0c;人们都需要检测气体以保障生命安全和生产活动的正常进行。随着科技的不断进步&#xff0c;气体检测技术也经历了从古代到现代的巨大变革&#xff0c;现代气体检测方法和古代气体检…

经常戴耳机有什么危害呢?一文读懂长时间使用耳机都有哪些危害

经常佩戴耳机可能会出现滋生细菌、引起炎症反应、损伤听力等危害。 1、滋生细菌&#xff1a;长时间戴耳机&#xff0c;会导致耳道堵塞&#xff0c;从而导致耳内潮湿&#xff0c;容易滋生细菌。 2、引起炎症反应&#xff1a;长时间戴耳机&#xff0c;会对耳道口造成机械性的压…

HttpRunner自动化之响应中文乱码处理

响应中文乱码&#xff1a; 当调用接口&#xff0c;响应正文返回的中文是乱码时&#xff0c;一般是响应正文的编码格式不为 utf-8 导致&#xff0c;此时需要根据实际的编码格式处理 示例&#xff1a; 图1中 extract 提取title标题&#xff0c;output 输出 title 变量值&#x…

景联文科技GPT教育题库:AI教育大模型的强大数据引擎

GPT-4发布后&#xff0c;美国奥数队总教练、卡耐基梅隆大学数学系教授罗博认为&#xff0c;这个几乎是用“刷题”方式喂大的AI教育大模型的到来&#xff0c;意味着人类的刷题时代即将退出历史舞台。 未来教育将更加注重学生的个性化需求和多元化发展&#xff0c;借助GPT和AI教育…

基于ssm的网上购物平台设计+jsp论文

摘 要 信息数据从传统到当代&#xff0c;是一直在变革当中&#xff0c;突如其来的互联网让传统的信息管理看到了革命性的曙光&#xff0c;因为传统信息管理从时效性&#xff0c;还是安全性&#xff0c;还是可操作性等各个方面来讲&#xff0c;遇到了互联网时代才发现能补上自古…

酷开科技 | 酷开系统9.2,开启个性化时代

现代人&#xff0c;总喜欢不走寻常路&#xff0c;以彰显自己的不同。酷开系统的个性化推荐就能满足你的这类需求&#xff0c;既能给你想要的内容&#xff0c;又能给你与众不同的体验&#xff01; 想听音乐了&#xff1f;打开酷开系统音乐频道&#xff0c;随机播放为你推荐的歌曲…

OSPF基本概念与配置(完整版)

目录 路由分类 OSPF概述 一、OSPF的工作过程 二、报文类型 三、OSPF区域 四、OSPF单区域实验案例 拓扑 需求 配置步骤 配置命令 五、OSPF邻居表解析 六、OSPF路由角色 七、OSPF多区域实验案例 拓扑 需求 配置步骤 配置命令 八、邻居建立失败的原因(已广播型网络…

生成式AI:开发效率的提升者

文章目录 摘要引言应用方向应用示例1. 自动化代码生成2. 智能样式生成3. 自动化测试与调试 总结&#x1f636; 写在结尾 摘要 生成式AI作为一种新兴技术&#xff0c;正在迅速改变软件开发的方式。通过自动化和优化开发流程&#xff0c;它可以帮助开发人员更快地生成代码、测试…

springboot项目 java -jar xxx.jar 没有主清单属性解决方法

1.在pom文件中添加如下 <plugins><!--解决SpringBoot打包成jar后运行提示没有主清单属性--><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><fork…

Android中的Intent

一.显式Intent 显示Intent是明确目标Activity的类名 1. 通过Intent(Context packageContext, Class<?> cls)构造方法 2.通过Intent的setComponent()方法 3.通过Intent的setClass/setClassName方法 通过Intent(Context packageContext, Class<?> cls)构造方法 通…

TikTok被限流怎么办?破解0播放方法在这!

Tiktok是目前增长较快的社交平台&#xff0c;也是中外年轻一代首选的社交平台&#xff0c;许多出海品牌已经看到了TikTok营销的潜力&#xff0c;专注于通过视频、电商入驻来加入TikTok这片蓝海&#xff0c;加深品牌影响力&#xff0c;获得变现。 然而TikTok新手往往都会遇到一…

2023春季李宏毅机器学习笔记 05 :机器如何生成图像

资料 课程主页&#xff1a;https://speech.ee.ntu.edu.tw/~hylee/ml/2023-spring.phpGithub&#xff1a;https://github.com/Fafa-DL/Lhy_Machine_LearningB站课程&#xff1a;https://space.bilibili.com/253734135/channel/collectiondetail?sid2014800 一、图像生成常见模型…

使用 Swagger 导入 Postman: 最佳实践与步骤解析

Swagger和 Postman 都是常用的 API 测试工具&#xff0c;都有各自的优势。为了结合两者的优点&#xff0c;我们可以考虑将 Swagger 中的 API 定义导入到 Postman 中去&#xff0c;这样就可以利用 Postman 更强大的测试功能来测试 Swagger 定义的接口。 下面将以 Swagger Petst…

【本科生通信原理】【实验报告】【北京航空航天大学】实验一:通信原理初步

一、实验目的&#xff1a; 熟悉 MATLAB开发环境、掌握 MATLAB基本运算操作&#xff1b;熟悉和了解 MATLAB图形绘制基本指令&#xff1b;熟悉使用 MATLAB分析信号频谱的过程&#xff1b;掌握加性白高斯噪声信道模型 二、实验内容&#xff1a; 三、实验程序&#xff1a; 1、 f…