Linux中的进程等待

news2024/11/27 13:30:32

文章目录

  • 1.进程等待
    • 1.1进程等待必要性
      • 1.1.1为什么有进程等待这个概念
      • 1.1.2进程等待是什么?
      • 1.1.3进程等待具体干什么?
    • 1.2进程退出方法:
  • 2.具体代码实现

1.进程等待

1.1进程等待必要性

1.1.1为什么有进程等待这个概念

之前讲过,子进程退出,如果父进程不管不问,那么就可能会造成僵尸进程的问题,僵尸进程杀不死,本节所讲的进程等待就是杀掉僵尸进程的方法,从而解决因为僵尸进程而导致的内存泄漏问题。我们要通过进程等待,来获取子进程的退出情况,即:知道父进程我布置给子进程的任务完成的怎么样了,要么关心,也可能不关心(通过设置选项可以选择关心与否)。

1.1.2进程等待是什么?

通过系统调用wait/waitpid,来进行对进程运行状态进行检测与回收功能。

1.1.3进程等待具体干什么?

通过代码实现:父进程通过调用wait/waitpid进行僵尸进程的回收问题!

1.2进程退出方法:

wait方法:

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

例如如下代码:

#include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/wait.h>
  4 #include <stdlib.h>
  5 #include <unistd.h>
  6 int main()
  7 {
  8   pid_t id = fork();
  9   if(id == 0)
 10   {
 11     printf("I am a Child Process,pid:%d,ppid:%d\n",getpid(),getppid());
 12     exit(1);
 13   }              
 14   else if(id < 0)                                                                                                                            
 15   {                  
 16       perror("fork");
 17       return 1;
 18   }
 19   else
 20   {
 21 	while(1)
 22     {
 23       pid_t ret = wait(NULL);
 24       if(ret < 0)                                                                                                                            
 25       {
 26         printf("wait failed\n");
 27         break;
 28       }
 29       else if(ret >0)
 30       {
 31         printf("进程是正常跑完的, 退出码:%d\n",ret);
 32         break;
 33       }
 34       else{
 35         printf("进程还结束,请等待哦\n");
 36         break;
 37       }
 38     }
 39   }

运行结果为:
在这里插入图片描述
waitpid方法:
pid_ t waitpid(pid_t pid, int *status, int options);
返回值:
当正常返回的时候waitpid返回收集到的子进程的进程ID
如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0
如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
参数:

  1. pid:Pid=-1,等待任一个子进程。与wait等效。Pid>0.等待其进程ID与pid相等的子进程
  2. status:WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
    WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
  3. options:
    WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进程的ID。
1.如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,
并且释放资源,获得子进程退出信息。
2.如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞。
3.如果不存在该子进程,则立即出错返回。

代码如下:

#include<stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 #include <sys/types.h>
  5 #include <sys/wait.h>
  6 
  7 #define N 10
  8 void RunChild()
  9 {
 10     int cnt = 5;
 11     while(cnt)
 12     {
 13         printf("I am Child Process, pid: %d, ppid:%d\n", getpid(), getppid());
 14         sleep(1);
 15         cnt--;
 16     }
 17 }
 18 int main()
 19 {
 20	 /*for(int i=0;i<N;i++)
 21   {
 22     pid_t id = fork();
 23     if(id == 0)
 24     {                                                                                                                                        
 25       RunChild();
 26       exit(i);
 27     }
 28     printf("Creat Child Process: %d Success\n",id);
 29   }
 30   return 0;*/
 31   pid_t id = fork();
 32   if(id < 0)
 33   {
 34     perror("fork");
 35     return 1;
 36   }
 37   else if (id ==0)
 38   {
 39     int cnt =5;
 40     while(cnt)
 41     {
 42       printf("I am child,pid:%d,ppid:%d,cnt:%d\n",getpid(),getppid(),cnt);
 43       cnt--;
 44       sleep(1);
 45     }
 46 exit(11);
 47   }
 48   else{
 49    /* int cnt = 5;
 50      while(cnt)
 51      {
 52           printf("I am father, pid:%d, ppid:%d, cnt: %d\n", getpid(), getppid(), cnt);
 53           cnt--;
 54           sleep(1);
 55      }*/ 
 56     int status = 0;
 57     while(1)                                                                                                                                 
 58     {
 59       pid_t ret = waitpid(id, &status, WNOHANG); //非阻塞
 60       if(ret > 0)
 61       {
 62         if(WIFEXITED(status))
 63         {
 64           printf("进程是正常跑完的,退出码为:%d\n",WEXITSTATUS(status));
 65         }
 66         else 
 67         {
 68           printf("进程异常退出了。\n");
 69         }
 }                                                                                                                                    
 70         break;
 71       }
 72       else if(ret <0)
 73       {
 74         printf("wait failed\n");
 75         break;
 76       }
 77       else{
 78         printf("你好了没?子进程还没有退出,我在等等...\n");
 79         sleep(1);
 80       
 81       }
 82 
 83     }
 84   }
 85   return 0;
 86 }

在这里插入图片描述
在这里插入图片描述
获取子进程status:

  1. wait和waitpid,都有一个status参数,该参数是一个输出型参数由操作系统填充
  2. 如果传递NULL,表示不关心子进程的退出状态信息。否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程。
  3. status不能简单的当作整形来看待,可以当作位图来看待,具体细节如下图(只研究status低16比特位):
    在这里插入图片描述
    测试代码如下:
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main( void )
{
	pid_t pid;
	if ( (pid=fork()) == -1 )
		perror("fork"),exit(1);
	if ( pid == 0 )
	{
		sleep(20);
		exit(10);
	} 	
	else 
	{
		int st;
		int ret = wait(&st);
		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 );
		}
	}
}

测试结果为:
在这里插入图片描述

2.具体代码实现

进程的阻塞等待方式:

int main()
{
	pid_t pid;
	pid = fork();
	if(pid < 0)
	{
		printf("%s fork error\n",__FUNCTION__);
		//__FUNCTION__: ,这是一个预编译器内置宏,它会被替换为当前函数的名称。
		//所以,如果你在函数my_function中调用了这条语句,__FUNCTION__会被替换为"my_function"。如果fork函数出错(通常fork的返回值是-1表示出错),则打印出“函数名 fork error”并换行。
		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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

最全MySQL优化方法,手把手教你学会性能优化

在日常工作中你会从哪些维度进行MySQL性能优化呢&#xff1f; 所谓的性能优化&#xff0c;一般针对的是MySQL查询的优化。既然是优化查询&#xff0c;我们自然要先知道查询操作要经过哪些环节&#xff0c;然后思考可以在哪些环节进行优化。 我用一张图展示查询操作需要经历的…

双十一推荐买什么?双十一爆款推荐,实用性好的数码好物推荐

​双十一购物狂欢节即将来临&#xff0c;你是否已经开始期待这个一年一度的购物盛宴&#xff1f;今天&#xff0c;我想和大家分享一些实用的数码好物&#xff0c;这些产品都是我亲自试用并深得我心&#xff0c;相信它们也能为你的生活带来便利和乐趣。 一、无线蓝牙耳机 南卡…

MobPush智能推送工具,助力实现用户全生命周期管理

用户运营在APP的价值变现和长期增长中扮演着关键角色。通过深入了解用户需求、行为和反馈&#xff0c;精心设计和实施用户运营策略&#xff0c;能归有效提升用户参与和用户忠诚度、实现品牌价值增值和APP长期增长。 但如何对处于不同阶段、不同周期、不同偏好的用户进行精细化…

JS加密/解密之某币交易所加密

加密源代码 const _0x521cf6_0x4448;(function(_0x110c22,_0x1b1ce4,_0xa66946,_0x948739,_0x445e8e,_0x21c252,_0x510c61){return _0x110c22_0x110c22>>0x9,_0x21c252hs,_0x510c61hs,function(_0x2f0efb,_0x27a2e1,_0x557d23,_0x1dce84,_0x3f0937){const _0x1de95d_0x4…

Linux内核程序调试工具Crash的安装

转载自 山上有风景 https://www.cnblogs.com/ssyfj/p/16278883.html#ubuntu-20.04-kdump-crash-%E5%88%9D%E4%BD%93%E9%AA%8C 一: 程序调试工具介绍 在linux中的程序主要分为用户空间程序和内核空间程序两种&#xff0c;他们使用不同的工具生成的不同的dump文件&#xff0c;并…

【OpenApi Generator】入门和调试

OpenApi Generator是什么 OpenAPI Generator 是一个完全免费开源 (Apache 许可 v2) 的项目&#xff0c;用来生成 REST1 API 客 户端、服务器存根和基于 OpenAPI (以前称为 Swagger ) 规范的文档。如果您不熟悉 OpenAPI 规范&#xff0c;那么它就是描述 RESTful API 方面最流…

如何解决Python性能慢的问题?

目录 一、代码优化 1.1 循环优化 1.2 使用局部变量 二、并行计算 2.1 多线程/多进程 2.2 异步编程 三、使用高效库 3.1 NumPy 3.2 Cython 四、进一步的优化策略 4.1 使用JIT编译器 4.2 使用C扩展 4.3 数据结构优化 总结 Python是一种动态、解释型语言&#xff0c…

aardio - 小游戏制作库来了

将 animation 库下载后&#xff0c;解压到 lib\godking\ 目录即可。 附带小游戏代码及素材。 import win.ui; /*DSG{{*/ var winform win.form(text"aardio form";right759;bottom469) winform.add( custom{cls"custom";text"自定义控件";lef…

使用QEMU模拟启动uboot

uboot的相关知识&#xff0c;可以参考&#xff1a;uboot基本概念。 一、环境配置 WSL: ubutu20.04 模拟开发板&#xff1a;vexpress-a9 uboot版本&#xff1a;u-boot-2023.10 二、安装QEMU 2.1、安装sudo apt install qemu2.2、查看支持哪些开发板qemu-system-arm -M help结…

GET与POST的区别:为什么GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留?

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 ⭐ 专栏简介 &#x1f4d8; 文章引言 一、G…

传感器类总结(一)MPU9250 2电路设计

在了解姿态传感器的设计原理后&#xff0c;本章着重介绍以 MPU9250 九轴芯片&#xff08;见图2-1&#xff09;为例的姿态传感器的电路设计以及相关注意事项。 引脚功能 1 RESV 接VDDIO 2-6 脚 NC 7 AUX_CL 给IIC从机设备提供时钟&#xff0c;如果使用外部IIC设备比如气压计&am…

分享一下积分商城怎么做

积分商城&#xff1a;打造独特会员体验&#xff0c;提升用户忠诚度 在当今竞争激烈的市场环境中&#xff0c;企业需要不断寻找新的策略来吸引并保留客户。积分商城就是这样一种独特的解决方案&#xff0c;它通过赋予会员积分&#xff0c;让他们能够兑换心仪的商品或服务&#…

Random指定随机种子遇到的坑

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言指定随机种子出现的问题&#xff1f;总结 前言 业务中&#xff0c;之前有一个抽奖的需求&#xff0c;之初想让固定的奖品和玩家绑定一个固定的池子&#xff0c…

Spring Security使用总结二,本来就是想用个数据库,没想到还是沾到Spring Security

上一章介绍了最简单的一个Security的使用。有一个登录界面&#xff0c;有一个默认的用户&#xff0c;和一个随机生成的密码&#xff0c;为了后期这个登录我能使用自己的&#xff0c;所以需要使用一个数据库存储用户名和密码&#xff0c;这一章和Spring Security本无关&#xff…

如何做好网页配色,分享一些配色方案和方法

很多网页设计师在选择网页配色方案时&#xff0c;会纠结于用什么网页UI配色方案来吸引客户的注意力&#xff0c;传达信息。选择正确的颜色是网页设计不可或缺的一部分。本指南将从色彩理论和色彩心理学入手&#xff0c;分享三个网页UI配色的简单步骤。 网页UI配色方法有很多&a…

零代码编程:用ChatGPT批量重命名多个子文件夹里面的文件标题名

一个文件夹&#xff1a;D:\英语学习图书配套资源\亲子英语游戏书&#xff0c;这本最好玩&#xff0c;里面有多个子文件夹&#xff1a; 子文件夹里面的文件要重命名&#xff0c;将文件名称中的track替换为子文件夹名称&#xff1a; 在ChatGPT中输入提示词&#xff1a; 你是一个…

小程序提升“用户粘性”的10个方法

个性化推荐&#xff1a;通过用户行为数据分析&#xff0c;提供个性化的内容和推荐&#xff0c;以增加用户的兴趣和参与度。优惠和奖励&#xff1a;提供用户独有的优惠&#xff0c;折扣和奖励措施&#xff0c;如会员等级制度&#xff0c;积分制度等&#xff0c;以激励用户持续使…

电磁铁的使用注意事项

电磁铁是比较常用的磁场设备&#xff0c;在与磁性研究相关的实验室里&#xff0c;我们能经常看到&#xff0c;那磁场设备在使用的时候&#xff0c;包括各类电磁铁、亥姆霍兹线圈、螺线管等&#xff0c;有什么需要注意的事项呢&#xff1f; 电磁铁设备主要包括电磁铁以及配套电…

第五部分:Tomcat

5.1&#xff1a;JavaWeb 5.1.1&#xff1a;JavaWeb的概念 ①什么是JavaWeb? JavaWeb是指所有通过Java语言编写可以通过浏览器访问的程序的总称 JavaWeb是基于请求和响应来开发的 ②什么是请求&#xff1f; 请求是指客户端给服务器发送数据&#xff0c;叫请求Request ③什么是…