Linux之进程(四)(进程地址空间)

目录

一、程序地址空间

二、进程地址空间

1、概念

2、写时拷贝

3、为什么要有进程地址空间

四、总结


一、程序地址空间

我们先来看看下面这张图。这张图是我们在学习语言时就见到过的内存区域划分图。 

下面我们在Linux下看一看内存区域是不是也是这么划分的。

可见在Linux下也是符合上面的分布的。

那么下面我们来看看下面的代码: 

上面的代码中用fork函数创建了一个子进程,其中让子进程相将全局变量g_val该从100改为200后打印,而父进程先休眠3秒钟,然后再打印全局变量的值。
按我们之前所学的来说子进程打印的全局变量的值为200,而父进程是在子进程将全局变量改后再打印的全局变量,而且全局变量在整个程序中应该只有一个,那么也应该是200,但是代码运行结果如下:

从上面的结果中,我们可以看到父进程打印的全局变量g_val的值为100,而子进程打印的是改变后的200。但是,更奇怪的是在父子进程中打印的全局变量g_val的地址是一样的,也就是说父子进程在同一个地址处读出的值是不同。

这就很奇怪了。同一个地址处却存的是不同的值,这和我们之前所学的知识又冲突了。同一个地址的值不应该是一样的吗?这到底是怎么回事呢?

最好的解释就是:在同一个地址处获取到的值却不同,这只能说明我们打印出来的地址绝对不是物理地址。 那是什么地址呢?

事实上,我们在语言层面上打印出来的地址都不是物理地址,而是虚拟地址。所以就算父子进程当中打印出来的全局变量的地址(虚拟地址)完全相同,但是两个进程当中全局变量的值却是不同的。因为每一个进程都有一个属于自己的地址空间!所以即使是地址名相同,也是在不同的地址空间中。

那么这就要求操作系统通过某种方式帮助用户将虚拟地址转换成物理地址。

二、进程地址空间

1、概念

所以之前说‘程序的地址空间’是不准确的,准确的应该说成 ’进程地址空间‘。我们所说的地址空间区域划分并不是对物理内存进行区域划分,而是对进程地址空间进行区域划分。

进程地址空间不是内存,其本质上是内存中的一种内核数据结构,在Linux当中进程地址空间具体由结构体mm_struct实现。所以对于进程地址空间的区域划分,本质上是定义每个区间的结束和开始。

在结构体mm_struct当中,各个边界之间的每一个部分都代表一个虚拟地址,这些虚拟地址通过页表映射与物理内存建立联系。 

每个进程被创建时,其对应的进程控制块(task_struct)和进程地址空间(mm_struct)也会随之被创建。而操作系统可以通过进程的task_struct找到其对应的mm_struct,因为task_struct当中有一个结构体指针存储的是mm_struct的地址。

所以上面的代码结果我们就可以解释了。同一个变量,地址相同,其实是虚拟地址相同,内容不同其实是被页表映射到了不同的物理地址。

父子进程的进程地址空间当中的各个虚拟地址分别通过页表映射到物理内存的某个位置。

当子进程刚刚被创建时,子进程和父进程的数据和代码是共享的,即父子进程的代码和数据通过页表映射到物理内存的同一块空间。只有当父进程或子进程需要修改数据时,才将父进程的数据在内存当中重新开一块空间,拷贝一份,然后再进行修改。

这种在需要进行数据修改时再进行拷贝的方法,称为写时拷贝。

2、写时拷贝

~ 为什么要有写时拷贝?

进程具有独立性。多进程运行,需要独享各种资源,多进程运行期间互不干扰,不能让子进程的修改影响到父进程,也不能让父进程影响子进程。

~ 为什么不在创建子进程的时候就进行数据的拷贝?

子进程不一定会使用父进程的所有数据,并且在子进程不对数据进行写入的情况下,没有必要对数据进行拷贝,我们应该按需分配,在需要修改数据的时候再分配(延时分配),这样可以高效的使用内存空间。

写时拷贝是一种延时申请的技术,可以提高整机内存的使用率。

3、为什么要有进程地址空间

每一个进程都有自己的地址空间和页表,这样不仅麻烦而且理解成本也高,那么为什么要有虚拟地址?

~ 进程地址空间保证了数据的安全性

首先,我们先来看看如果我们直接使用物理内存会发生什么。如下图:我们在进程1中定义了一个指针char* ,因为我们现在是直接使用物理内存,所以char*直接指向了一个物理内存。如果我们进程1中的代码出现了错误,比如char* 指向了进程2中的地址,那么这样就会出问题,进程1的指针可以改变进程2的内容了。

所以操作系统不能让用户直接使用物理内存,于是就有了进程地址空间。

每个进程都有自己的进程地址空间,所有的进程都要通过页表映射到物理内存,而不同的进程会被映射到不同的物理内存中。万一进程越界非法访问、非法读写时,页表还可以进行拦截,不让其访问。而直接访问物理内存是无法拦截非法访问的,所以保证了内存数据的安全性。

~ 可以更方便的进行进程和进程的数据代码的解耦,保证了进程独立性

对于每一个进程而言,它们都有只属于自己的地址空间及页表,不同的进程通过页表映射到不同的物理内存上,所以一个进程数据的改变不会影响到另一个进程,保证了进程的独立性。可以做到物理内存分配和进程的管理之间不会相互影响。

~ 将内存分布有序化

因为在理论上,进程可以加载到物理内存的任意位置,所以在物理内存中几乎所有的代码和数据都是乱序的,而在进程地址空间中代码和数据的分布位置都是确定的。但是因为页表的存在,它可以将虚拟地址和物理地址进行映射,所以在进程的视角上,所有的内存分布都是有序的。

四、总结

其实,程序在编译时,编译器就会给每一个变量、每一个函数都编写一个地址,这个地址就是虚拟地址。当程序被加载到物理内存中,虚拟地址会被填写进页表的左侧。然后将一个代码加载到内存的什么位置的这个物理地址填写到页表的右侧。这就是映射关系的构建。

我们通常所说的地址,一般都是虚拟地址。而不是内存中的物理地址。

我们在语言中使用的new,malloc等申请的空间在本质上也都是申请的虚拟地址空间,而不是物理内存空间。而且申请了之后也不是直接拿到物理内存,只有当用户真正对物理地址空间进行访问的时候,才执行内存相关的管理算法,帮助用户从物理内存上申请空间,构建页表映射关系。然后用户再使用。

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

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

相关文章

圣诞树绘制合集-python绘制

使用Python绘制迷人的圣诞树 引言 随着圣诞节的临近,我们都希望以各种方式庆祝这个欢乐的节日。作为一名编程爱好者,你有没有想过用Python来创造节日的气氛呢?在这篇文章中,我将向你展示如何用Python绘制几种不同风格的圣诞树&a…

索尼(ILCE-7M3)MP4文件只能播放前两分钟修复案例

索尼的ILCE-7M3是一款经典设备,其HEVC编码效果是比较不错的,因此受到很多专业人士的青睐。之前我们说过很多索尼摄像机断电生成RSV文件修复的案例,今天来讲一个特殊的,文件已经正常封装但仅能播放前两分钟多一点的画面。 故障文件…

详细教程 - 从零开发 鸿蒙harmonyOS应用 第四节 (鸿蒙Stage模型 登录页面 ArkTS版 推荐使用)

在鸿蒙OS中,Ability是应用程序提供的抽象功能,可以理解为一种功能。在应用程序中,一个页面即一种能力,如登录页面,即具有登录功能的能力。以下是对鸿蒙新建项目的登录代码功能的详细解读和工作流程的描述: …

C++入门篇

呀哈喽,我是结衣。 了解完C的发展历程,我们当然也要会用C啊。今天这篇博客就是来帮助我们来入门C的,当然要入门C当然也要先学会C语言啦。在我学习C的过程中我会一直把C博客更新下去的。 C关键字 我们都知道C语言是有32个关键字的&#xff0…

json JSON.parse()与JSON.stringify()

JSON.parse() 属于解析 JSON.parse()方法解析一个JSON字符串为ECMAScript值,返回解析后的值, JSON.parse({}); // -> {}JSON.parse([]); // -> []JSON.parse(1); // -> {}注意:JSON.parse()解析的JSON字符串不允许以逗…

Python-数据分析可视化实例图

Python-数据分析可视化实例图 一:3D纹理图 运行效果图: Python代码: import math from typing import Unionimport pyecharts.options as opts from pyecharts.charts import Surface3Ddef float_range(start: int, end: int, step: Union[…

分享66个Java源码总有一个是你想要的

分享66个Java源码总有一个是你想要的 学习知识费力气,收集整理更不易。 知识付费甚欢喜,为咱码农谋福利。 链接:https://pan.baidu.com/s/1hKlZJB3KrHcOuKWyV1xjKw?pwd6666 提取码:6666 项目名称 ava web个人网站项目 ea…

不是生活有意思,是你热爱生活它才有意思

明制汉服的设计 同样是一款很重工的外套 细节上也是做到了极致 顺毛毛呢面料 领口袖口拼接仿貂毛环保毛条 前胸欧根纱刺绣圆形布 袖子贴民族风珠片刺绣织带 门襟搭配金属子母扣,真盘扣设计 时尚经典,搭配马面裙孩子穿上 真的很有气质奢华富贵 …

程序人生15年人生感悟

计算机程序员并不是一件什么高大上的职业。而仅仅是一份普通的工作。就像医生能治病救人,我们能治蓝屏救程序,我们都在为这个世界默默的做出自己的贡献。刻意或无意宣扬某个职业高大上,其实质是对其它行业从业者的不公平。但是有些人却常常这…

Node.js安装教程

虽然网上Node.js的安装教程有很多,但是基本上都是千篇一律。虽然跟着网上内容安装,却总会遇到乱七八糟的问题。为此,我写下这篇文章,除了描述node的安装教程,还会解释这样安装的过程起到一个什么作用。 文章大致上分为…

【PHP入门】1.2-常量与变量

-常量与变量- PHP是一种动态网站开发的脚本语言,动态语言特点是交互性,会有数据的传递,而PHP作为“中间人”,需要进行数据的传递,传递的前提就是PHP能自己存储数据(临时存储) 1.2.1变量基本概…

微服务实战系列之ZooKeeper(下)

前言 通过前序两篇关于ZooKeeper的介绍和总结,我们可以大致理解了它是什么,它有哪些重要组成部分。 今天,博主特别介绍一下ZooKeeper的一个核心应用场景:分布式锁。 应用ZooKeeper Q:什么是分布式锁 首先了解一下&…

04 python函数

4.1 函数的快速开发体验 """ 演示,快速体验函数的开发和使用 """#需求,统计字符串的长度,不使用内置函数len()str1 itheima str2 itcast str3 python#定义一个计数的变量 count 0 for i in str1:count 1…

FPGA使用乘法的方式

FPGA使用乘法的方式 方法一:直接使用乘法符“*” 源代码 module multiply(input [7:0] a,input [7:0] b,output wire [15:0] result);(*use_dsp48 = "yes"*) wire [15:0] result;assign result = a*b; endmodule仿真代码 module multiply_tb();reg [7:0] a; re…

java minio通过getPresignedObjectUrl设置(自定义)预签名URL下载文件的响应文件名之minio源码改造方案

Minio预签名URL自定义响应文件名之Minio源码改造 需求说明Minio源码改造一、环境准备二、下载Minio源代码三、修改源代码1.修改cmd目录下的api-router.go这个代码文件2.将filename参数值设置到响应头4.修改验证签名时是否需要带入filename参数验证 四、大功告成,编译…

残差网络中的BN (Batch Normalization 批标准化层)的作用是什么?

文章目录 什么是BN (Batch Normalization 批标准化层)一、BN层对输入信号进行以下操作:二、BN 层有什么作用? 什么是BN (Batch Normalization 批标准化层) BN层的全称是Batch Normalization层,中文可以翻译为批标准化…

如何让.NET应用使用更大的内存

我一直在思考为何Redis这种应用就能独占那么大的内存空间而我开发的应用为何只有4GB大小左右,在此基础上也问了一些大佬,最终还是验证下自己的猜测。 操作系统限制 主要为32位操作系统和64位操作系统。 每个进程自身还分为了用户进程空间和内核进程空…

Mybatis-Spring整合原理:MapperFactoryBean和MapperScannerConfigurer的区别及源码剖析

文章目录 引言MapperFactoryBean的用法和优缺点MapperScannerConfigurer的用法和优缺点MapperFactoryBean源码分析MapperScannerConfigurer源码分析Spring容器初始化流程回顾核心方法:postProcessBeanDefinitionRegistryBeanDefinitionRegistryPostProcessor和BeanF…

Java 并发编程(六)-Fork/Join异步回调

一、并发编程 1、Fork/Join分支合并框架 Fork/Join它可以将一个大的任务拆分成多个子任务进行并行处理,最后将子任务结果合并成最后的计算结果,并进行输出。Fork/Join框架要完成两件事情: Fork:把一个复杂任务进行分拆&#xff0…

下午好~ 我的论文【CV边角料】(第三期)

文章目录 CV边角料Pixel ShuffleSENetCBAMGlobal Context Block (GC)Criss-Cross Attention modules (CC) CV边角料 Pixel Shuffle Real-Time Single Image and Video Super-Resolution Using an Efficient Sub-Pixel Convolutional Neural Network pixelshuffle算法的实现流…