初识--Linux的虚拟地址空间

重新了解地址空间

在学习c/c++语言的时候,大家一定见过以下这张图

说的是程序会加载在如图的结构上,实际上,我们真的对他很了解吗,而在Linux进程控制这,就会有一个奇怪的现象

前提提要:简要介绍一下fork函数

进程=内核数据结构(PCB)+自己的代码以及数据

在Linux中,fork可以从当前进程创建一个新进程,创建的新进程为子进程,而当前当前进程就是子进程的父进程,而子进程会以父进程为模板,创建子进程

头文件在#include <unistd.h>
pid_t fork(void);
返回值:自进程中返回0,父进程返回子进程id,出错返回-1

进程调用fork,当控制转移到内核中的fork代码后,内核做:
1.分配新的内存块和内核数据结构给子进程
2.将父进程部分数据结构内容拷贝至子进程
3.添加子进程到系统进程列表当中

4.fork返回,开始调度器调度

这里先不深入讲解fork函数,主要是为接下来的行为做铺垫

请看以下代码

                                                                                                                              #include <stdio.h>                                                                                                                                                 
#include <unistd.h>
#include <stdlib.h>
int g_val = 0;//全局变量int main()
{pid_t id = fork();//创建进程if(id < 0){//创建进程错误perror("fork");return 0;}else if(id == 0){ //子进程返回码为0 这里就是子进程printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);//getpid返回当前进程的pid}else{ //父进程printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);}sleep(1);return 0;
}

运行结果也如我们所料

parent[19376]: 0 : 0x601050
child[19377]: 0 : 0x601050

 子进程和父进程的g_val的地址都是相同的,很正常.

奇怪的事情

如果我们对以上代码的两个进程的其中一个进行修改,会发生什么呢,大家不妨大胆猜测一下

                                                                                                                              #include <stdio.h>                                                                                                                                                 
#include <unistd.h>
#include <stdlib.h>
int g_val = 0;//全局变量int main()
{pid_t id = fork();//创建进程if(id < 0){//创建进程错误perror("fork");return 0;}else if(id == 0){ //子进程返回码为0 这里就是子进程g_val+=10;//我们在子进程这修改g_val的值printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);//getpid返回当前进程的pid}else{ //父进程printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);}sleep(1);return 0;
}

在这里 我们修改了全局变量g_val的值,嗯,因为是全局的,g_val地址对应的值只有一个,所以父子进程都应该打印g_val=10 对吧? 我们来看看实际的结果

parent[19907]: 0 : 0x601050
child[19908]: 10 : 0x601050

欸 不是哥们,啊? 你这俩进程全局变量的对应地址不都是一样的吗,咋打印出的值还不一样啊,难道技术创新了,一个地址可以对应两个值? 当然不是的,接下来,我们就来讲讲为什么会出现这种奇怪的现象 

物理地址所对应的值有且只能有一个,所以我们可以退出以下结论

1.变量内容不一样,所以父子进程输出的变量绝对不是同一个变量

2.但地址值是一样的,说明,该地址绝对不是物理地址
3.在Linux地址下,这种地址叫做 虚拟地址
4.我们在用C/C++语言所看到的地址,全部都是虚拟地址!物理地址,用户一概看不到,由操作系统OS统一管理

那么------------> 也就是说 操作系统必须负责将 虚拟地址 转化成 物理地址,

进程地址空间

所以之前说‘程序的地址空间’是不准确的,准确的应该说成进程地址空间,那该如何理解呢?

那么操作系统是如何将进程虚拟地址转换成物理地址的呢?

页表&虚拟进程地址空间

操作系统其实是利用一种页表的操作将进程虚拟地址空间映射到物理地址空间,而这个页表去映射的过程,其实就有点类似于哈希的映射的关系

上面的图就足矣说明问题,同一个变量,地址相同,其实是虚拟地址相同,内容不同其实是被页表映射到了不同物理地址!!!

而操作系统为什么要这么做呢

这样做有两个好处

1.将物理内存从无序转换成有序,让进程以统一的视角,看待内存

2.将进程管理内存管理进行耦合

地址空间+页表也就是保护内存安全的一个重要手段

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

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

相关文章

Sy-linux下常用的网络命令linux network commands

linux下的网络命令非常强大&#xff0c;这里根据教材需要&#xff0c;列出来常用的网络命令和场景实例&#xff0c;供参考。 一、命令列表&#xff1a; Command Description ip Manipulating routing to assigning and configuring network parameters traceroute Identi…

RabbitMQ Stream插件使用详解

2.4版为RabbitMQ流插件引入了对RabbitMQStream插件Java客户端的初始支持。 RabbitStreamTemplateStreamListener容器 将spring rabbit流依赖项添加到项目中&#xff1a; <dependency><groupId>org.springframework.amqp</groupId><artifactId>sprin…

Java工程师常见面试题:Java基础(一)

1、JDK 和 JRE 有什么区别&#xff1f; JDK是Java开发工具包&#xff0c;它包含了JRE和开发工具&#xff08;如javac编译器和java程序运行工具等&#xff09;&#xff0c;主要用于Java程序的开发。而JRE是Java运行环境&#xff0c;它只包含了运行Java程序所必须的环境&#xf…

Java springboot使用EasyExcel读Excel文件,映射不到属性值,对象属性值都是null

如果你的类上有这个注解&#xff0c;去掉火或注释掉就可以了 Accessors(chain true)解决方法

vue 常用的日历排班,带农历显示组件(2024-04-16)

显示当前月日历组件&#xff0c;里面带农历或节日显示 后面可以丰富一些国家法定节假期的业务需求 代码 js-calendar.js 文件 var lunarInfo [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, //1900-19090x04ae0, 0x0a5b6, 0…

【大数据】分布式文件系统HDFS

目录 1.什么是分布式文件系统 2.HDFS的特点 3.HDFS的核心概念 4.HDFS的体系结构 5.HDFS的配置建议 6.HDFS的局限性 7.HDFS的存储机制 7.1.数据冗余机制 7.2.错误与恢复 8.HDFS数据读写过程 1.什么是分布式文件系统 分布式文件系统是整个大数据技术的基础&#xff0c…

常用序号、标点符号 相关正则表达式

(?:[\(|&#xff08;|\[])?\d[\]|\)&#xff09;|\、]|[\u2460-\u2473]|[\u4e00-\u5341][.|、]匹配序号 \d\.(?!\d)|\d、常规序号匹配&#xff1a; rule1: 标准格式1. 2、 rule2:排除小数 [^\u4E00-\u9FA5\uFF00-\uFFEFa-zA-Z0-9\s]所有符号 [\u3000-\u303F\uFF00-\uFFE…

STM32 软件I2C方式读取MT6701磁编码器获取角度例程

STM32 软件I2C方式读取MT6701磁编码器获取角度例程 &#x1f4cd;相关篇《STM32 软件I2C方式读取AS5600磁编码器获取角度例程》&#x1f33f;《Arduino通过I2C驱动MT6701磁编码器并读取角度数据》&#x1f530;MT6701芯片和AS5600从软件读取对比&#xff0c;只是读取的寄存器和…

LeetCode 409—— 最长回文串

阅读目录 1. 题目2. 解题思路3. 代码实现 1. 题目 2. 解题思路 要想组成回文串&#xff0c;那么只有最中间的字符可以是奇数个&#xff0c;其余字符都必须是偶数个。 所以&#xff0c;我们先遍历一遍字符串&#xff0c;统计出每个字符出现的次数。 然后如果某个字符出现了偶…

xcode c++项目设置运行时参数

在 Xcode 项目中&#xff0c;你可以通过配置 scheme 来指定在运行时传递的参数。以下是在 Xcode 中设置运行时参数的步骤&#xff1a; 打开 Xcode&#xff0c;并打开你的项目。在 Xcode 菜单栏中&#xff0c;选择 "Product" -> "Scheme" -> "E…

滤波器笔记(杂乱)

线性相位是时间平移&#xff0c;相位不失真 零、基础知识 1、用相量表示正弦量 https://zhuanlan.zhihu.com/p/345546880 https://www.zhihu.com/question/347763932/answer/1103938667 A s i n ( ω t θ ) ⇔ A e j θ ⇔ A ∠ θ Asin(\omega t\theta) {\Leftrightarrow…

[沫忘录]MySQL索引

[沫忘录]MySQL索引 索引概述 优点 提高数据检索效率&#xff0c;降低数据库IO成本通过索引对数据进行排序&#xff0c;降低数据排序成本&#xff0c;降低CPU消耗 缺点 索引会占用一定空间当更新数据时&#xff0c;也需更新索引数据&#xff0c;这会降低数据的更新效率 索引…