Linux程序的地址空间,进程终止

个人主页:点我进入主页

专栏分类:C语言初阶  C语言进阶  数据结构初阶    Linux    C++初阶    算法

欢迎大家点赞,评论,收藏。

一起努力,一起奔赴大厂

一.程序的地址空间

1.1程序的地址空间的引入

        我们知道frok可以创建子进程,子进程会继承父进程的大部分属性,如果我们我们给出一个g_val,在子进程和父进程中输入g_val的值以及g_val的地址,会是怎样的结果呢?我们看下面代码:

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>int main()
{int g_val=100;pid_t id=fork();if(id==0){int cnt=5;while(cnt--){printf("I an child process,g_val=%d,&g_val=%p,pid=%d, ppid=%d\n",g_val,&g_val,getpid(),getppid());sleep(1);}}else if(id>0){while(1){printf("I an father process,g_val=%d,&g_val=%p,pid=%d, ppid=%d\n",g_val,&g_val,getpid(),getppid());sleep(1);}}return 0;
} 

我们运行后可以看到

父进程的g_val的地址和子进程的g_val的地址相同 ,如果我们,我们将子进程的代码修改,每次让g_val的值加1,会是怎样的结果?我们可以看到一下

g_val的值不同,但是g_val的地址却一样,这是为什么呢?在c语言时我们知道一个地址对应一个值,为什么在这里会出现一个地址对应两个值?这打破了我们的常规认知,其实不然,在以前我们写的都是一个进程,在这里是两个进程,这其中自然有一些差别,那这是如何实现的呢?这与程序的地址空间有关,这里的地址也不是物理地址,是虚拟地址

1.2程序地址空间概图

1.2.1不修改值时

        程序的地址空间是怎样的呢?我们可以看下面的图

 父进程有一个g_val虚拟地址是0x7ffe258b87bc,在父进程的地址空间中会有个初始化数据,里面的g_val地址也是虚拟地址,同时还有一个页表,页表有两部分,一部分是虚拟地址,一部分是物理地址,它相当于一个映射进程的虚拟地址对应者相应的物理地址。由于子进程会继承父进程的代码和数据以及大部分属性,所以子进程会继承父进程的task_struct,继承父进程的地址空间,父进程的页表,也就是说会进程一次浅拷贝

1.2.2修改值时

        在上面我们有一个修改g_val的值,那它和上面的过程一样吗?事实上是类似的,当我们想要修改值时,会发生一次写时拷贝,写时拷贝是什么呢?写的时候再进程修改,我们看下面的图

 子进程会将父进程的代码。数据。mm_struct,task_struct进行拷贝,在物理空间中重新开辟一次g_val进行写。

1.3理解地址空间

        进程有独立的地址空间,独立的页表,如果父进程和子进程不写,一个全局变量(类似于g_val的变量),默认会被子进程和父进程共享(只读)。那为什么这样干呢?如果我们不采用写时拷贝,只要有一个子进程就会在物理内存上开辟一块空间,这样有一定的缺点,有时候我们并不会修改值,会造成没有意义的空间开辟,那我们采用写时拷贝会不会很慢呢?当然不会,我们开辟的时候就拷贝,和用的时候再拷贝,我们采用写时拷贝还会减少拷贝的次数,效率更快,更节省空间,写时拷贝就是我都你不会用

1.3.1为什么要有地址空间(地址空间的优点)

        首先页表和地址空间可以将无序变为有序,我们知道我们开辟的空间是随机开辟的,通过页表的映射关系可以有效的将空间变得有序。其次可以将进程管理模块(页表和地址空间)和内存模块(物理空间)解耦,在程序进程检测时它检测到地址空间有就可以进行执行,因此我们只在地址空间上申请内存,填写页表的左侧,用的时候再在物理空间上开辟内存,这样也是可以的,还有一种情况我们先看下面的图:

假如 我们有2MB的内存,我们映射到物理空间上后,可以先执行1MB的内存,当者1MB执行完后可以先将这1MB内存释放,删除页表的关系,但是地址空间不变,这样我们看着还是2MB。最后访问越界时,如果页表中查不到这个地址,os就会阻止这个请求,实现对物理内存的保护,例如我们一个数组a[10],我们访问a[200]就会被os拦截。

1.3.2进一步理解页表和写时拷贝

        在页表中不仅仅有虚拟地址和物理地址这两部分,还有一个检测是否在内存中以及权限,我们先说是否在内存中,它用一个0个1来表示0不在内存中,1在内存中,那什么时候会显示0呢?

当内存不足时,会将一部分页表的内容唤出到磁盘中,还记得我们进程挂起的swap分区吗,这里和那个类似,当被唤出到磁盘中后这里就会显示为0 。

当我们创建子进程后父进程和子进程中 权限都会被修改为r,当我们想要修改时发生写时拷贝,权限修改为w。当操作系统检测到错误时会先进行检测是否不在物理内存中(缺页中断,也就是页表中为0),然后检测是否需要发生写时拷贝(检测权限是否为r),都不是才进程异常处理

二.进程的终止

2.1进程终止的3中状态

2.1.1代码跑完结果正确

我们先运行下面代码

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>int main()
{printf("pid=%d,ppid=%d\n",getpid(),getppid());return 0;
} 

运行后输入指令

echo $?

echo $?是返回我们前一个程序的返回码,我们将上面代码return 100然后运行然后输入指令echo$?可以看到

当我们再执行一次ehco $?可以看到

这是输出echo $?的退出码。

2.2.1代码跑完,结果错误

        在这里我们需要先知道退出码有什么作用,在一个父进程中我们需要知道子进程的退出状态,是成功还是失败?失败的原因是什么?所以出现了退出码这个概念。退出码有很多我们需要知道每一个退出码是什么吗?其实不需要,我们有一个函数可以知道每个退出码是什么意思,我们看下面代码

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<string.h>int main()
{for(int errorcode=0;errorcode<=255;errorcode++){printf("errorcode=%d->%s\n",errorcode,strerror(errorcode));}printf("pid:%d,ppid=%d\n",getpid(),getppid());return 0;
} 

我们运行代码

2.2.3出现异常

        运行时,进程崩溃了,os会将进程杀掉一旦出现了异常退出码就没有意义了,为什么出现异常原因是进程出现了异常,本质说os进程发出信号。例如我们运行下面代码:

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<string.h>int main()
{while(1){printf("pid=%d,ppid=%d\n",getpid(),getppid());sleep(1);}return 0;
} 

我们输入指令

kill -9 pid

可以看到

我们可以输入指令

kill -11 pid

2.2检测进程终止顺序

        首先检测进程是否出现异常,出现异常就不用管退出码,如果出现退出码,代码一定跑完了,再看退出码,异常后退出码是什么都没有任何意义。所以衡量一个进程退出我们只需要知道程序的退出码和推出信号。在进程的task_struct中有一个退出码和一个推出信号,当进程结束时会将这个给父进程。

2.3进程如何终止(exit和_exit)

        首先可以通过return实现进程终止。也可以通过exit来实现进程终止,exit在结束时会冲刷一次缓冲区,我们运行下面代码

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>int main()
{printf("hello process.exe\n");printf("exit");exit(0);
} 

运行后可以看到

两个都输出了。

还有一种是_exit函数,我们看下面代码

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>int main()
{printf("hello process.exe\n");printf("exit");_exit(0);
} 

运行后

我们可以看到exit会冲刷一次缓冲区,_exit不会冲刷缓冲区。

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

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

相关文章

【SpringBoot实战篇】获取用户详细信息

1 明确需求 1需要获取用户详细信息 2 接口文档 1基本信息 2请求参数 无 3 响应数据 响应数据类型&#xff1a;application/json 响应参数说明&#xff1a; 响应数据样例 3 思路分析 1用户名在请求头里获取 4 开发 4.1 控制器usercontroller GetMapping("/userInfo")p…

实用软件与高效工具汇总(持续更新...)

名人说&#xff1a;莫愁千里路&#xff0c;自有到来风。 ——钱珝 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、软件1、文件搜索类2、截图贴图类3、软件卸载类4、录屏gif类5、护眼调光类6、流程绘图类7、图片…

怎么压缩图片200k以下?压缩图片到指定大小

在工作中&#xff0c;会遇到在某些系统要上传照片&#xff0c;但是对于上传的照片大小有限制&#xff0c;比如限制大小不能超过200KB等&#xff0c;而外业拍摄的照片往往会超过限制的大小&#xff0c;那么这时就需要对照片进行压缩。尤其是我们在面对大量图片需要处理的时候&am…

面试经典150题——跳跃游戏 II

面试经典150题 day10 题目来源我的题解方法一 动态规划方法二 贪心 题目来源 力扣每日一题&#xff1b;题序&#xff1a;45 我的题解 方法一 动态规划 动态规划&#xff0c;当j位置可达i位置时&#xff1a;dp[i]Math.min(dp[i],dp[j]1); 时间复杂度&#xff1a;O( n 2 n^2 n…

mysql按季度统计数据

最近遇到按表里得交付时间换成季度取统计&#xff0c;如下&#xff1a; select sp.Id,sp.title,QUARTER(sp.expected_delivery_time) dateStr,CONCAT(DATE(MIN(sp.expected_delivery_time)),至,DATE(MAX(sp.expected_delivery_time))) dateStr2,sp.DemandType,sp.IndustryGrou…

centos7安装mysql5.7笔记

1 配置yum仓库 1.1更新密钥 #更新密钥 rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022 1.2 下载使用wget命令下载MySQL的repo文件 #下载使用wget命令下载MySQL的repo文件 wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm 2 使用…

鸿蒙系列--第一个程序HelloWorld

一、下载安装 下载DevEco Studio&#xff08;https://developer.huawei.com/consumer/cn/deveco-studio/&#xff09;并安装 二、创建第一个鸿蒙应用 Next Compile SDK&#xff1a;鸿蒙SDK版本 Mode&#xff1a;ArkTS的声明式开发范式与类Web 开发范式&#xff0c;官方主推S…

二维码如何调整样式?美化二维码生成器的用法

美化二维码功能是一个很常用的二维码编辑功能&#xff0c;一般用来修改二维码颜色、添加logo、更高码点、设置容错率等设置&#xff0c;可以通过简单的步骤将普通的黑白二维码调整成其他的样式。那么美化二维码生成器的使用方法是什么样的呢&#xff1f;下面就让小编来给大家讲…

哈希和布隆过滤器

哈希 布隆过滤器 一致性哈希

Linux-进程间通信:System V消息队列

目录 System V IPC概述标识符与IPC Key System V消息队列创建或打开一个消息队列发送消息接收消息控制消息队列1、IPC_STAT2、IPC_SET3、IPC_RMID 查看系统当前的消息队列代码示例 System V IPC&#xff08;Inter-Process Communication&#xff09;是一组用于在 Unix-like 操作…

3D模型人物换装系统(五 模型核批之后模型uv不正确)模型UV不正确

3D模型人物换装系统&#xff08;五 模型核批之后模型uv不正确&#xff09;模型UV不正确 介绍展示Maya导入查看uvUnity中测试分析没合批为什么没有问题总结 介绍 最近在公司里给公司做模型优化合批的时候发现了模型的uv在合批之后无法正常展示&#xff0c;这里找了很多的原因&a…

牛客网:环形链表的约瑟夫问题

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;每日一练 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f3dd;1.问题描述&#xff1a; 前言&#xff1a; 约瑟夫问题 有很多种解决办法&#xff0c;下面我们用链表进行解题 题目链…

【H4012】3.3V5V12V24V30V,3.5A大电流温度低 高效同步降压芯片IC DC-DC

您提到的“3.3V, 5V, 12V, 24V, 30V, 3.5A 高效同步降压芯片IC DC-DC”是指一种能够将较高电压&#xff08;例如24V或30V&#xff09;降至较低电压&#xff08;例如3.3V, 5V或12V&#xff09;的直流-直流&#xff08;DC-DC&#xff09;转换器。这种转换器通常使用同步降压技术&…

Springboot项目中,异步编程底层实现原理详解(二)

本系列文章简介&#xff1a; 在现代的开发中&#xff0c;异步编程已经成为了必备的技能。随着计算机性能的提升和多核处理器的普及&#xff0c;异步编程可以充分利用系统资源&#xff0c;提高程序的性能和响应速度。在Spring Boot项目中&#xff0c;异步编程也得到了广泛的应用…

短视频流媒体平台的系统设计

1. 功能需求: 我们的系统有两类参与者 内容创作者 •上传任何类型的视频&#xff08;格式编解码器&#xff09;•视频可以被删除•视频元数据•必填项: 标题&#xff0c;作者&#xff0c;描述•选填项: 分类/标签列表•可以随时更新•当视频对观众可用时&#xff0c;向内容创作…

力扣110. 平衡二叉树

思路&#xff1a;与二叉树最大高度类似&#xff0c;但是这里需要返回 -1 的高度来标识不是平衡二叉树&#xff0c;判断左右子树的高度相差大于1则不平衡&#xff0c;否则就是平衡。 class Solution {public boolean isBalanced(TreeNode root) {int ans func(root);if(ans >…

【人工智能基础】状态空间搜索

状态空间法 状态空间&#xff1a;一个问题全部可能的状态以及其关系的集合。 状态空间图&#xff1a;以图的形式表示问题的状态空间&#xff0c;节点对应状态&#xff0c;边对应状态转移算子&#xff0c;边上的权对应转移所需的代价 问题的解&#xff1a;是从最开始状态到目…

聊聊路径规划算法(二)——图搜索法

图搜索法通过利用已有的环境地图和版图中的障碍物等数据信息建立&#xff0c;由起点至结束点的可行路线。一般分为深度最优和广度最优二种走向。深度优先算法优先拓展搜索深度较大的节点&#xff0c;因此能够更迅速的获得下一个可行路径&#xff0c;不过深度优先算法获取的第一…

Adobe Firefly是否将重新定义AI视频编辑领域?|TodayAI

Adobe最近发布了一段令人瞩目的视频&#xff0c;详细展示了其最新推出的Adobe Firefly视频模型。这一模型集成了尖端的生成式人工智能技术&#xff0c;带来了一系列颠覆性的视频编辑功能&#xff0c;引发了业界的广泛关注和讨论。 视频中的旁白充满热情地宣布&#xff1a;“Ad…

Rabbit加密算法:性能与安全的完美结合

title: Rabbit加密算法&#xff1a;性能与安全的完美结合 date: 2024/4/19 19:51:30 updated: 2024/4/19 19:51:30 tags: Rabbit加密对称加密流密码密钥调度安全分析实际应用加密算法 第一章&#xff1a;引言 1. 加密算法的基本概念和应用 加密算法是一种通过对数据进行转换…