Linux——进程控制(一)进程的创建与退出

目录

一、进程创建

1.写时拷贝

2.创建多个进程

二、进程终止

1.main函数的返回值

2.bash中的$? 

3.自定义退出码

4.C语言的错误码

5.错误码与退出码的区别

6.代码异常终止

7.exit函数

8.总结


一、进程创建

在之前,我们学过linux中的非常重要的函数——fork。他可以从已存在进程中创建一个新进程,新进程为子进程,而原进程为父进程

1.写时拷贝

我们知道,fork之后,父子代码共享,经常会出现同一个变量,父子通过操作的不同,这个变量的值也不同,这个时候就会发生写时拷贝。写时拷贝是如何进行的呢?

通过这张图可以看到,fork之后数据段变成了只读, 子进程需要对数据进行写入,就得需要写时拷贝,写时拷贝需要重新申请空间,进行拷贝,再修改页表,这都是操作系统在帮我们处理的,那么操作系统怎么知道你这一份数据需要进行写时拷贝呢?

父进程创建子进程的时候首先将自己的读写权限修改成只读,然后再创建子进程,这些操作用户并不知道,可能对某些数据进行写入,这样在页表处就会进行权限判断,发现用户没有权限,操作系统此时就会介入,操作系统会判断用户的操作

如果该区域本该是可读可写的,是操作系统修改为只读的,因此操作系统会认为用户的操作不算错误,就会触发重新申请内存再拷贝内容的策略机制,这就是写时拷贝。

如果出错,就直接报错,不做额外处理。

写时拷贝完成后,再将对应的内容在页表中修改为可读可写(没有进行写实拷贝的内容依然是只读的)。这样用户就可以正常访问了。

这是一种惰性分离,每次发生写时拷贝都要开辟空间,将写时拷贝的时间越往后延迟,操作系统就有更多的资源


这里还有一个小问题:你要写入的时候写就完事了,为何还要拷贝一份呢?

因为覆盖和修改是不一样的,很多情况,我们只是想要修改内容的某一部分,这样先拷贝再修改会更合适一点。

2.创建多个进程

我们知道fork的常规用法如下两种

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

如果要创建多个进程来帮我们处理,应该怎么做呢?  直接上代码

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

#define N 10

typedef void (*callback)();

void Work()
{
    int cnt = 10;
    while(cnt)
    {
        printf("我是一个子进程, pid: %d, ppid :%d, cnt:%d\n",getpid(),getppid(),cnt--);
        sleep(1);
    }
}

void CreateProcess(int n,callback cb)
{
    int i = 0;
    for(;i<n;i++)
    {
        sleep(1);
        pid_t id = fork();
        if(id == 0)
        {
            //child                                                                    
            printf("子进程创建成功: %d\n",i);
            cb();
            exit(0);
        }
    }
}

int main()
{
    CreateProcess(N,Work);
    sleep(100);
    return 0;
}

这代码对于学过fork的我们来讲,并不算难,多了一个函数指针而已,下面是运行代码。

二、进程终止

进程退出的场景如下三种

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

1.main函数的返回值

我们写C语言程序时,main函数一般都会return 0。只要执行到了return语句,证明我们的代码肯定是运行完毕了的,只是结果还不知道是否正确

在多进程环境中,我们创建子进程的目的是完成父进程不方便办的事,那我们怎么知道子进程办得怎么样,虽然我们可以打印出来看看结果,但在有一些情况下不方便或者不能打印出来看看,此时就可以通过return的值来查看的,main函数的返回值,就叫做进程的退出码,0通常表示成功,非0表示失败。父进程可以通过获取子进程退出码(即main函数的返回值)来得知子进程做得咋样。

成功的还好,知道你吧事情办得很好,如果返回非0,代表这个事没办好,我们得知道是因为什么原因失败的,我们可以用不同的数字表示不同的原因。但纯数字能表示出错的原因,但是不便于人阅读,因此有一个函数交 strerror 函数。

如下可以打印出strerror各个数字代表的出错原因

有很多很多原因 

2.bash中的$? 

在bash命令中输入echo $? 可以打印出最近一个子进程执行完毕时的退出码,有点类似于之前我们学习的环境变量,变量名为?,加了$可以打印出变量里的内容。

如下代码中return 10,执行该进程,bash最后获取到的子进程退出码就为10

但是我们继续执行echo $? 后面退出码就会变成0,因为echo也是bash的一个子进程,执行echo语句后,echo语句就是最后一个子进程了,echo又是正常退出的,因此再输入echo $? 得到的值为0。

main函数的退出码是可以被父进程获取的,用来判断子进程的运行结果 

3.自定义退出码

退出码可以使用C语言内置的,也可以自定义,自己对退出码做解释,因为退出码退出多少(也就是return 返回多少是你自己设置的) 

如下就是自定义的退出码,如果你的代码根据用户的操作出现了错误,可以返回响应的值,来知道发生了什么错误。

4.C语言的错误码

在学习C语言的时候,我们接触过一个名叫 errno 的全局变量,他会在程序在运行过程中调用某些库函数或者系统接口出错的时候,被自动设置。也是记录最后一次出错的信息。

如下代码,只读的方式打开一个不存在文件,我们看一下erron的变化与出错信息

发现错误码为2,错误信息为没有该文件

5.错误码与退出码的区别

  • 错误码通常是衡量调用库函数或者系统调用接口的调用情况。(系统调用也能更改错误码是因为Linux是用C语言写的,提供了C式接口)
  • 退出码通常是一个进程退出的时候,他的退出结果。

他们两个共同的地方在于当失败的时候,用来衡量函数、进程出错时的详细原因。

如下,让错误码与退出码保持了一致

6.代码异常终止

前面五点主要学习的是进程正常退出的问题,可能会有出错码和退出码,如果一个进程异常终止,那么他的退出码也就没有了意义

比如代码中存在 /0 错误,又比如段错误,栈溢出等等,程序就会崩溃,进程就异常了,就不会继续运行了,本质是操作系统将该进程杀掉了,操作系统会用信号的方式将进程杀掉。

输入 kill -l 可以查看 kill命令的信号 

这里我们一直运行一个进程,然后输入kill -8 + 进程pid,就可以通过浮点数错误的方式终止该进程。输入其他方式杀死,也会有相应的错误报告。 

 因此,查看进程是否出现异常,我们只需看有没有收到信号即可

7.exit函数

C语言退出函数 exit() ,括号内部可以添加数字,这也是退出码的一种。 

exit与return的区别在于

在非main函数中return 并不会终止进程,main函数会终止进程。

在任意函数中exit都会终止进程。

8.总结

查看进程运行完毕,结果是否正确,只需要看退出码即可

查看进程异常终止,只需要查看收到的信号是什么即可。

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

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

相关文章

Fastadmin下拉选择菜单

下拉菜单效果图如下所示 对应的表字段为 cid int(11) unsigned NOT NULL DEFAULT ‘1’ COMMENT ‘分类ID 1 新手 2VIP 3基金产品’ 步骤如下&#xff1a; 一、lang/zh-cn 中找到对应的文件&#xff0c;添加 配置 二、Model 中添加方法 三、控制器中添加 四、add.html中 …

leetcode刷题(javaScript)——栈相关场景题总结

在LeetCode刷题中&#xff0c;栈是一个非常有用的数据结构&#xff0c;可以解决许多问题&#xff0c;包括但不限于以下几类问题&#xff1a; 括号匹配问题&#xff1a;例如检查括号序列是否有效、计算表达式的值等。逆波兰表达式求值&#xff1a;使用栈来实现逆波兰表达式的计算…

Python实现链表:从基础到应用

一、引言 链表是一种常见的数据结构&#xff0c;它由一系列节点组成&#xff0c;每个节点包含数据和指向下一个节点的指针。链表在内存中的存储不是连续的&#xff0c;这使得它在插入和删除操作上具有较高的效率。本文将使用Python语言来实现一个简单的链表&#xff0c;并展示其…

零基础学编程,中文编程工具之进度标尺构件的编程用法

零基础学编程&#xff0c;中文编程工具之进度标尺构件的编程用法 一、前言 今天给大家分享的中文编程开发语言工具 进度条构件的用法。 编程入门视频教程链接 https://edu.csdn.net/course/detail/39036 编程工具及实例源码文件下载可以点击最下方官网卡片——软件下载——…

力扣:35. 搜索插入位置

力扣&#xff1a;35. 搜索插入位置 描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 示例 1: 输入: nums [1,…

windows系统玩《模拟人生 4》 免安装版本

本文介绍如何在windows系统上玩《模拟人生 4》这个游戏&#xff0c;无需安装&#xff0c;直接玩&#xff01; 首先下载百度网盘分享的文件&#xff0c;这里下载文章末尾。 下载完成后先点击 language-change.exe 将游戏语言更改为英文&#xff0c;默认是俄语&#xff0c;根本…

sqllabs的order by注入

当我们在打开sqli-labs的46关发现其实是个表格&#xff0c;当测试sort等于123时&#xff0c;会根据列数的不同来进行排序 我们需要利用这个点来判断是否存在注入漏洞&#xff0c;通过加入asc 和desc判断页面有注入点 1、基于使用if语句盲注 如果我们配合if函数&#xff0c;表达…

B端系统:导航机制设计,用户体验提升的法宝

Hi&#xff0c;大家好&#xff0c;我是贝格前端工场&#xff0c;从事8年前端开发的老司机。很多B端系统体验不好很大一部分原因在于导航设计的不合理&#xff0c;让用户无所适从&#xff0c;大大降低了操作体验&#xff0c;本文着重分析B端系统的导航体系改如何设计&#xff0c…

[CISCN2019 华北赛区 Day2 Web1]Hack World 1 题目分析与详解

一、分析判断 进入靶机&#xff0c;主页面如图&#xff1a; 主页面提供给我们一条关键信息&#xff1a; flag值在 表flag 中的 flag列 中。 接着我们尝试输入不同的id&#xff0c;情况分别如图&#xff1a; 当id1时&#xff1a; 当id2时&#xff1a; 当id3时&#xff1a; 我…

【IO流系列】ConvertStream 转换流

转换流 1. 概述2. 作用3. 字符编码和字符集3.1 字符编码3.2 字符集 4. InputStreamReader字符转换输入流4.1 构造方法4.2 代码示例 5. OutputStreamWriter字符转换输出流5.1 构造方法5.2 代码示例 6. 练习6.1 练习1&#xff1a;转换文件编码6.2 练习2&#xff1a;读取文件数据 …

Spring 源码解析

文章目录 前言相关Spring的定义接口整体代码StartupStep contextRefresh this.applicationStartup.start("spring.context.refresh")prepareRefresh()obtainFreshBeanFactory()registerBeanPostProcessors(beanFactory)SpringAOP原码流程EnableAspectJAutoProxyAnno…

基于java+springboot女士电商平台系统源码+文档设计

基于javaspringboot女士电商平台系统源码文档设计 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言 文末获取源…

GaussDB跨云容灾:实现跨地域的数据库高可用能力

背景 金融、银行业等对数据的安全有着较高的要求&#xff0c;同城容灾建设方案&#xff0c;在绝大多数场景下可以保证业务数据的安全性&#xff0c;但是在极端情况下&#xff0c;如遇不可抗力因素等&#xff0c;要保证数据的安全性&#xff0c;就需要采取跨地域的容灾方案。 …

【大咖分享】:千帆AppBuilder:我的AI大模型科研搭子

同济子豪兄介绍 不知不觉&#xff0c;我做人工智能科技区博主已经七年了。从斯坦福公开课系列&#xff0c;到精读AI经典论文系列&#xff0c;从编程奇妙夜&#xff0c;到两天搞定AI毕业设计系列。我们为十几万学员&#xff0c;提供人工智能各方向的论文课程、生涯规划、课题辅…

ROS2体系框架

文章目录 1.ROS2的系统架构2.ROS2的编码风格3.细谈初始化和资源释放4.细谈配置文件5.ROS2的一些命令6.ROS2的核心模块6.1 通信模块6.2 功能包6.3 分布式6.4 终端命令和rqt6.5 launch6.6 TF坐标变换6.7 可视化RVIZ 1.ROS2的系统架构 开发者的工作内容一般都在应用层&#xff0c;…

【计算机网络】五种IO模型与IO多路转接之select

文章目录 一、五种IO模型二、非阻塞IO1.fcntl2.实现函数SetNoBlock3.轮询方式读取标准输入 三、I/O多路转接之select1.初识select2.select函数原型3.socket就绪条件4.select的特点5.select缺点6.select使用案例--只读取数据的server服务器1.err.hpp2.log.hpp3.sock.hpp4.select…

游泳耳机哪种款式好?简单6招教你选到高品质机型!

游泳是一项全身性的运动&#xff0c;不仅能帮助我们保持身体健康&#xff0c;还能让我们在水中放松心情&#xff0c;享受水中的乐趣。而音乐则是人们生活中不可或缺的一部分&#xff0c;它能带给我们快乐和力量。当游泳与音乐相结合&#xff0c;游泳耳机应运而生&#xff0c;为…

MySQL-MHA搭建、故障测试

一、架构说明 MHA&#xff08;Master High Availability&#xff09;是一个用于 MySQL 主从复制管理和自动故障转移的开源工具集。MHA 的主要目的是提供 MySQL 环境的高可用性和自动故障转移功能&#xff0c;确保在主库发生故障时能够快速切换到备库&#xff0c;降低业务中断时…

机器人组装、充电桩组装行业生产管理MES系统免费用

​随着工业4.0和智能制造的兴起&#xff0c;企业对于生产过程的数字化、智能化需求日益迫切。传统的MES系统实施周期长、成本高&#xff0c;成为许多企业数字化转型的瓶颈。而低代码开发平台的出现为这一问题提供了新的解决思路。 ​一、万界星空科技低代码平台的优势&#xff…

【市工信】2024年青岛市绿色工厂、绿色工业园区等绿色制造示范申报

科大睿智小编从青岛市工信局了解到&#xff0c;为深入贯彻绿色发展理念&#xff0c;牢固树立绿色低碳发展导向&#xff0c;进一步完善绿色制造体系&#xff0c;培育绿色制造先进典型&#xff0c;根据《工业和信息化部关于印发<绿色工厂梯度培育及管理暂行办法>的通知》&a…