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

Linux中的进程等待

文章目录

  • 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   else20   {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 108 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 ){ //childprintf("child is run, pid is : %d\n",getpid());sleep(5);exit(257);} else{int status = 0;pid_t ret = waitpid(-1, &status, 0);//阻塞式等待,等待5Sprintf("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 ){ //childprintf("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;
}

相关文章:

  • Spring-Spring 之底层架构核心概念解析
  • Zabbix如何监控腾讯云NAT网关
  • 离散傅里叶变换中的能量守恒公式(帕斯瓦尔定理)及其程序举例验证
  • 根据Word模板,使用POI生成文档
  • Datawhale-AIGC实践
  • 【服务器】Java连接redis及使用Java操作redis、使用场景
  • pytorch笔记 GRUCELL
  • mediasoup-cluster横向扩容机制
  • mac flutter pb解析报错:protoc-gen-dart: program not found or is not executable
  • 蓝桥杯官网练习题(正则问题)
  • openGauss学习笔记-114 openGauss 数据库管理-设置安全策略-设置帐号有效期
  • gcc: __linux__
  • [SSD综述 1.4] SSD固态硬盘的架构和功能导论
  • Julia文件读写函数:write和read
  • 无mac电脑获取app的公钥的方法
  • “大数据应用场景”之隔壁老王(连载四)
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • docker-consul
  • iOS仿今日头条、壁纸应用、筛选分类、三方微博、颜色填充等源码
  • JAVA SE 6 GC调优笔记
  • Redash本地开发环境搭建
  • unity如何实现一个固定宽度的orthagraphic相机
  • Xmanager 远程桌面 CentOS 7
  • 对象引论
  • 服务器从安装到部署全过程(二)
  • 判断客户端类型,Android,iOS,PC
  • 驱动程序原理
  • 如何利用MongoDB打造TOP榜小程序
  • 使用 Docker 部署 Spring Boot项目
  • 提醒我喝水chrome插件开发指南
  • 一文看透浏览器架构
  • 用 Swift 编写面向协议的视图
  • 带你开发类似Pokemon Go的AR游戏
  • ​一文看懂数据清洗:缺失值、异常值和重复值的处理
  • #《AI中文版》V3 第 1 章 概述
  • (4)事件处理——(7)简单事件(Simple events)
  • (DenseNet)Densely Connected Convolutional Networks--Gao Huang
  • (Ruby)Ubuntu12.04安装Rails环境
  • (超简单)构建高可用网络应用:使用Nginx进行负载均衡与健康检查
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (理论篇)httpmoudle和httphandler一览
  • (转) 深度模型优化性能 调参
  • (转)Google的Objective-C编码规范
  • .bashrc在哪里,alias妙用
  • .java 指数平滑_转载:二次指数平滑法求预测值的Java代码
  • .net core使用ef 6
  • .net oracle 连接超时_Mysql连接数据库异常汇总【必收藏】
  • .NET学习教程二——.net基础定义+VS常用设置
  • [ 常用工具篇 ] POC-bomber 漏洞检测工具安装及使用详解
  • [20160807][系统设计的三次迭代]
  • [2018-01-08] Python强化周的第一天
  • [Android] Implementation vs API dependency
  • [BZOJ4016][FJOI2014]最短路径树问题