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

进程终止与进程等待

fork 函数

fork 函数是 Linux 中一个非常重要的函数,它的作用是从已存在的进程中创建一个新进程。这个新进程就是当前进程的子进程。

fork() 函数使用方法:它在头文件 #include <unistd.h> 中,函数原型为

pid_t fork(void);

用一个 pid_t 类型的变量来接收 fork() 函数的返回值。当创建进程成功时,fork() 函数会给子进程返回 0,给父进程返回新创建的子进程的 id;当创建失败时,fork() 函数会返回 -1(给父进程返回,因为子进程根本没创建出来)

当创建子进程成功后,操作系统会做:

  • 分配新的内存块和内核数据结构给子进程
  • 将父进程部分数据结构内容拷贝至子进程
  • 添加子进程到系统进程列表当中
  • fork返回,开始调度器调度

当一个进程调用fork之后,就有两个二进制代码相同的进程。但它们都运行到相同的地方后,每个进程都会可以开始它们自己的旅程。可以使用下面的代码测试(Linux系统):

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main(void)
{pid_t pid = fork();printf("Before: pid is %d\n", getpid());if (pid == -1) perror("fork()"), exit(1);if (pid == 0){printf("child:pid is %d, fork return %d\n", getpid(), pid);}else{printf("After:pid is %d, fork return %d\n", getpid(), pid);}sleep(1);return 0;
}

运行结果:

fork()函数 内核示意图

fork() 函数的常规用法及错误原因

常规用法

  • 一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请求,生成子进程来处理请求。
  • 一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数 

错误原因

  • 系统中有太多的进程
  • 实际用户的进程数超过了限制

C/C++中捕捉错误的方式(代码运行完毕,结果错误)

errno 是C语言调用C函数时的错误码,当调用函数出错时,它会在内部给出错误码(数字),但这个数字往往我们不知道是什么错误,那我们就要用 strerror 函数来解析这个错误码。strerror 函数可以将错误码以字符串的形式描述起来。

代码异常终止

当代码异常终止时,一般操作系统会给这个进程发信号,让这个进程以某种错误而终止,其表现就是这个进程被操作系统杀掉!它的内部逻辑类似于手动调用 kill 指令。

kill -n id

n 为选项,表示各种信号;id 为被发送信号进程的 id

使用如下指令可以查看 Linux 中全部的信号

kill -l

进程终止

进程退出有三种场景:

  • 代码运行完毕,结果正确
  • 代码运行完毕,结果不正确
  • 代码异常终止

这三种情况可以用2个数字组合完全覆盖!

当进程正常终止时:可以通过 echo $? 查看进程退出码。

进程正常终止有三种情况:1. 从main返回;2. 调用exit;3. 调用_exit

异常退出:ctrl + c,信号终止

exit() 函数

#include <unistd.h>
void exit(int status);

status 定义了进程的终止状态,也就是进程的结果正确还是不正确。status 是一个整形值,父进程可以通过 wait函数来获取该值,得到子进程的最终执行结果!

_exit() 函数

#include <unistd.h>
void _exit(int status);

_exit() 函数与 exit() 函数的作用可以说是一模一样,只是在细节上有所差异:在终止进程时,exit() 函数会自动刷新缓冲区,而_exit() 函数不会!

其实相当于 exit()函数 是先调用了 _exit() 函数,如图

由此可以得出一个结论:我们所认识的缓冲区,并不在操作系统内部!否则 exit() 和 exit() 都应该能刷新缓冲区。

进程等待

什么是进程等待?

通过 wait/waitpid 的方式,让父进程对子进程进行资源回收的等待过程。那为什么要进行等待呢?

第一,可以解决子进程僵尸问题带来的内存泄漏问题(进程僵尸只有父进程回收才能解决,且不能被杀掉,所以这是目前必须使用进程等待解决的问题);第二,父进程创建子进程的目的,就是让子进程来完成任务,而父进程需要知道子进程任务到底完成的如何,就必须通过等待的方式来获取子进程退出的信息(两个数字:退出码和信号)这个退出信息也许并不是必须的,但是系统需要提供这样的基础功能!

如何进行等待

在 Xshell 终端中输入如下指令,查看 waitpid 和 wait 的使用方式

wiat 和 waitpid 方法

man waitpid

wait 函数:

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

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

waitpid 函数

返回值:当正常返回的时候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。

那么父进程是如何得知子进程的退出信息呢?

子进程在退出的时候,要修改状态 Z,并将自己的退出信息和退出码写入 pcd 中,父进程通过读取子进程的 pcd 获取这些信息。注意:不能使用全局变量获取子进程的信息,因为进程之间具有独立性,各有各的进程地址空间,子进程对数据的修改不改变父进程中的数据!

获取子进程的 status

当需要获取子进程的 status时,通常采用位图的思想,使用位运算!

如图,经过位运算得到需要的数字:

是否收到信号的判定方法:exit sig 是否等于0,等于0说明没收到信号,不等于0说明收到了异常的信号;当一个进程异常了(收到信号),exit code 就变得没有意义了。

进程的阻塞等待和非阻塞等待

设 wait/waitpid 的返回值为 rid 

  • rid > 0 :等待成功
  • rid == 0:等待成功,但对方(子进程)还没有退出
  • rid < 0:等待失败 

对于 waitpid 方法而言,它的第三个参数 options 可以控制父进程是阻塞等待还是非阻塞等待。

阻塞等待:子进程不退出,父进程就一直等待子进程,waitpid 不返回。这种情况在计算机中叫 宕(dang)机或应用夯(hang)住了。这种等待的缺点就是父进程在等待的过程中,什么事都做不了!

进程的阻塞式等待代码

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(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;
}

非阻塞等待:如果子进程的退出条件不满足,wait/waitpid 不会阻塞,而是立即返回!所以非阻塞等待一般要重复读多次调用,这种一般叫做:非阻塞轮询方案进行进程等待 这样做的好处是:在子进程没有退出的情况下,父进程可以在等待的过程中,顺便做一些占用时间比较少的事情。

进程的非阻塞式等待代码

#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;
}

相关文章:

进程终止与进程等待

fork 函数 fork 函数是 Linux 中一个非常重要的函数&#xff0c;它的作用是从已存在的进程中创建一个新进程。这个新进程就是当前进程的子进程。 fork() 函数使用方法&#xff1a;它在头文件 #include <unistd.h> 中&#xff0c;函数原型为 pid_t fork(void); 用一个…...

MySQL 基础知识(六)之数据查询(二)

目录 6 数值型函数 7 字符串函数 8 流程控制函数 9 聚合函数 10 分组查询 (group by) 11 分组过滤 (having) 12 限定查询 (limit) 13 多表查询 13.1 连接条件关键词 (on、using) 13.2 连接算法 13.3 交叉连接 (cross join) 13.4 内连接 (inner join) 13.5 外连接 …...

蓝桥杯嵌入式STM32G431RBT6知识点(主观题部分)

目录 1 前置准备 1.1 Keil 1.1.1 编译器版本及微库 1.1.2 添加官方提供的LCD及I2C文件 1.2 CubeMX 1.2.1 时钟树 1.2.2 其他 1.2.3 明确CubeMX路径&#xff0c;放置芯片包 2 GPIO 2.1 实验1&#xff1a;LED1-LED8循环亮灭 ​编辑 2.2 实验2&#xff1a…...

ELAdmin 部署

后端部署 按需修改 application-prod.yml 例如验证码方式、登录状态到期时间等等。 修改完成后打好 Jar 包 执行完成后会生成最终可执行的 jar。JPA版本是 2.6&#xff0c;MyBatis 版本是 1.1。 启动命令 nohup java -jar eladmin-system-2.6.jar --spring.profiles.active…...

计算机功能简介:EC, NVMe, SCSI/ISCSI与块存储接口 RBD,NUMA

一 EC是指Embedded Controller 主要应用于移动计算机系统和嵌入式计算机系统中&#xff0c;为此类计算机提供系统管理功能。EC的主要功能是控制计算机主板上电时序、管理电池充电和放电&#xff0c;提供键盘矩阵接口、智能风扇接口、串口、GPIO、PS/2等常规IO功能&#xff0c;…...

linux上安装bluesky的步骤

1、设备上安装的操作系统如下&#xff1a; orangepiorangepi5b:~$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.2 LTS Release: 22.04 Codename: jammy 2、在用户家目录下创建一个目录miniconda3目录&a…...

视频监控需求八问:视频智能分析/视频汇聚平台EasyCVR有何特性?

最近TSINGSEE青犀视频在与业内伙伴进行项目合作的过程中&#xff0c;针对安防监控可视化视频管理系统EasyCVR视频融合平台在电信运营商项目中的应用&#xff0c;进行了多方面的项目需求沟通。今天我们就该项目沟通为案例&#xff0c;来具体了解一下用户关心度较高的关于视频智能…...

django rest framework 学习笔记2

注意&#xff1a;该文章部分摘抄之百度&#xff0c;仅当做学习笔记供小白使用&#xff0c;若侵权请联系删除&#xff01; 显示关联表的数据&#xff0c;本示例会显示所有的关联的数据信息 from rest_framework import serializers from .models import Student class StudentM…...

第四篇【传奇开心果系列】Python文本和语音相互转换库技术点案例示例:pyttsx3自动化脚本经典案例

传奇开心果短博文系列 系列短博文目录Python文本和语音相互转换库技术点案例示例系列 短博文目录前言一、雏形示例代码二、扩展思路介绍三、批量处理文本示例代码四、自定义语音设置示例代码五、结合其他库和API示例代码六、语音交互系统示例代码七、多语言支持示例代码八、添加…...

model.train()和model.eval()两种模式的原理

1. model.train() 在使用 pytorch 构建神经网络的时候&#xff0c;训练过程中会在程序上方添加一句model.train()&#xff0c;作用是 启用 batch normalization 和 dropout 。 如果模型中有BN层&#xff08;Batch Normalization&#xff09;和 Dropout &#xff0c;需要在 训练…...

docker的底层原理六: 联合文件系统(UnionFS)

Docker的底层存储原理基于联合文件系统&#xff08;UnionFS&#xff09;。 联合文件系统&#xff08;UnionFS&#xff09;是一种特殊的文件系统&#xff0c;它允许独立地叠加多个目录层&#xff0c;呈现给用户的是这些目录层的联合视图。这种结构使得在Docker中&#xff0c;不…...

【动态规划专栏】专题一:斐波那契数列模型--------1.第N个泰波那契数

本专栏内容为&#xff1a;算法学习专栏&#xff0c;分为优选算法专栏&#xff0c;贪心算法专栏&#xff0c;动态规划专栏以及递归&#xff0c;搜索与回溯算法专栏四部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握算法。 &#x1f493;博主csdn个人主页&#xff1a;小…...

自养号测评低成本高效率推广,安全可控

测评的作用在于让用户更真实、清晰、快捷地了解产品以及产品的使用方法和体验。通过买家对产品的测评&#xff0c;也可以帮助厂商和卖家优化产品缺陷&#xff0c;提高用户的使用体验。这进而帮助他们获得更好的销量&#xff0c;并更深入地了解市场需求。因此&#xff0c;测评在…...

ubuntu22.04@laptop OpenCV Get Started: 015_deep_learning_with_opencv_dnn_module

ubuntu22.04laptop OpenCV Get Started: 015_deep_learning_with_opencv_dnn_module 1. 源由2. 应用Demo2.1 C应用Demo2.2 Python应用Demo 3. 使用 OpenCV DNN 模块进行图像分类3.1 导入模块并加载类名文本文件3.2 从磁盘加载预训练 DenseNet121 模型3.3 读取图像并准备为模型输…...

【elk查日志 elastic(kibana)】

文章目录 概要具体的使用方式一&#xff1a;查找接口调用历史二&#xff1a;查找自己的打印日志三&#xff1a;查找错误日志 概要 每次查日志&#xff0c;我都需要别人帮我&#xff0c;时间长了总觉得不好意思&#xff0c;所以这次下定决心好好的梳理一下&#xff0c;怎么查日…...

RapidMiner数据挖掘2 —— 初识RapidMiner

本节由一系列练习与问题组成&#xff0c;这些练习与问题有助于理解多个基本概念。它侧重于各种特定步骤&#xff0c;以进行直接的探索性数据分析。因此&#xff0c;其主要目标是测试一些检查初步数据特征的方法。大多数练习都是关于图表技术&#xff0c;通常用于数据挖掘。 为此…...

基于STM32的光照检测系统设计

基于STM32的光照检测系统设计 摘要: 随着物联网和智能家居的快速发展,光照检测系统在智能环境控制中扮演着越来越重要的角色。本文设计了一种基于STM32的光照检测系统,该系统能够实时检测环境光强度,并根据光强度调节照明设备,实现智能照明控制。本文首先介绍了系统的总体…...

车辆管理系统设计与实践

车辆管理系统是针对车辆信息、行驶记录、维护保养等进行全面管理的系统。本文将介绍车辆管理系统的设计原则、技术架构以及实践经验&#xff0c;帮助读者了解如何构建一个高效、稳定的车辆管理系统。 1. 系统设计原则 在设计车辆管理系统时&#xff0c;需要遵循以下设计原则&…...

板块一 Servlet编程:第四节 HttpServletResponse对象全解与重定向 来自【汤米尼克的JAVAEE全套教程专栏】

板块一 Servlet编程&#xff1a;第四节 HttpServletResponse对象全解与重定向 一、什么是HttpServletResponse二、响应数据的常用方法三、响应乱码问题字符流乱码字节流乱码 四、重定向&#xff1a;sendRedirect请求转发和重定向的区别 在上一节中&#xff0c;我们系统的学习了…...

漫谈:C/C++ char 和 unsigned char 的用途

C/C的字符默认是有符号的&#xff0c;这一点非常的不爽&#xff0c;因为很少有人用单字节表达有符号数&#xff0c;毕竟&#xff0c;ASCII码是无符号的&#xff0c;对字符的绝大多数处理都是基于无符号的。 这一点在其它编程语言上就好很多&#xff0c;基本上都提供了byte这种类…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

mac:大模型系列测试

0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何&#xff0c;是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试&#xff0c;是可以跑通文章里面的代码。训练速度也是很快的。 注意…...

高分辨率图像合成归一化流扩展

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 1 摘要 我们提出了STARFlow&#xff0c;一种基于归一化流的可扩展生成模型&#xff0c;它在高分辨率图像合成方面取得了强大的性能。STARFlow的主要构建块是Transformer自回归流&#xff08;TARFlow&am…...

小智AI+MCP

什么是小智AI和MCP 如果还不清楚的先看往期文章 手搓小智AI聊天机器人 MCP 深度解析&#xff1a;AI 的USB接口 如何使用小智MCP 1.刷支持mcp的小智固件 2.下载官方MCP的示例代码 Github&#xff1a;https://github.com/78/mcp-calculator 安这个步骤执行 其中MCP_ENDPOI…...

41道Django高频题整理(附答案背诵版)

解释一下 Django 和 Tornado 的关系&#xff1f; Django和Tornado都是Python的web框架&#xff0c;但它们的设计哲学和应用场景有所不同。 Django是一个高级的Python Web框架&#xff0c;鼓励快速开发和干净、实用的设计。它遵循MVC设计&#xff0c;并强调代码复用。Django有…...