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

news2024/12/24 2:23:57

目录

一、程序地址空间

二、进程地址空间

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.coloradmin.cn/o/1317577.html

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

相关文章

浅谈MapReduce

MapReduce是一个抽象的分布式计算模型,主要对键值对进行运算处理。用户需要提供两个自定义函数: map:用于接受输入,并生成中间键值对。reduce:接受map输出的中间键值对集合,进行sorting后进行合并和数据规…

RabbitMq交换机详解

目录 1.交换机类型2.Fanout交换机2.1.声明队列和交换机2.2.消息发送2.3.消息接收2.4.总结 3.Direct交换机3.1.声明队列和交换机3.2.消息接收3.3.消息发送3.4.总结 4.Topic交换机4.1.说明4.2.消息发送4.3.消息接收4.4.总结 5.Headers交换机5.1.说明5.2.消息发送5.3.消息接收5.4.…

Linux(23):Linux 核心编译与管理

编译前的任务:认识核心与取得核心原始码 Linux 其实指的是核心。这个【核心(kernel)】是整个操作系统的最底层,他负责了整个硬件的驱动,以及提供各种系统所需的核心功能,包括防火墙机制、是否支持 LVM 或 Quota 等文件系统等等&a…

数据分析为何要学统计学(2)——如何估计总体概率分布

明确总体的概率分布类型及参数是进行数据分析的基础,这项工作称为分布推断与参数估计。在总体分布及其参数不明确的情况下,我们可以利用手头掌握的样本来完成这项工作。具体过程由以下步骤组成。 第一步,样本统计特性直观估计 我们采用Seab…

虚拟机VirtualBox和VMware安装Ubuntu16配置静态IP

计算机集群安装之前,准备先在虚拟机上尝试一下,网上多是采用VMware虚拟机和CentOS系统,个人则准备采用已经安装好的VirtualBox虚拟机和Ubuntu16,但遇到第一个问题即是配置静态IP,那么对于以上两种虚拟机静态IP配置的问…

(数据结构)单链表的查找和长度计算

代码实现 #include<stdio.h> #include<stdlib.h> typedef struct LNode {int data;struct LNode* next; }LNode,*LinkList; //创建头结点 LNode* InitList(LinkList L) {L (LNode*)malloc(sizeof(LNode));if (L NULL){return NULL;}L->data 0;L->next N…

掌握STL中stack和queue的用法(零基础/小白,全方面了解)

目录 1. stack的概念 2. stack的接口 2.1 构造函数&#xff08;初始化&#xff09; 2.2 赋值 2.3 存取操作 2.4 大小操作 3. queue的概念 4. queue的接口 4.1 构造函数 4.2 赋值操作 4.3 存取操作 4.4 大小操作 stack和queue接口函数很少&#xff0c;只要大家多敲一两…

设计模式(3)--对象结构(3)--组合

1. 意图 将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。 2. 三种角色 抽象组件(Component)、组合式节点(Composite)、叶节点(Leaf) 3. 优点 3.1 定义了包含基本对象和组合对象的类层次结构。 客户代码中&…

八大排序——快速排序(霍尔 | 挖空 | 前后指针 | 非递归)

我们今天来讲讲八大排序中的快速排序&#xff0c;快速排序最明显的特点就是排序快&#xff0c;时间复杂度是O&#xff08;N* logN&#xff09;&#xff0c;但是坏处就是如果排序的是一个逆序的数组的时候&#xff0c;时间复杂度是O&#xff08;N^2&#xff09;,还不用我们的插入…

【Hive_03】单行函数、聚合函数、窗口函数、自定义函数、炸裂函数

1、函数简介2、单行函数2.1 算术运算函数2.2 数值函数2.3 字符串函数&#xff08;1&#xff09;substring 截取字符串&#xff08;2&#xff09;replace 替换&#xff08;3&#xff09;regexp_replace 正则替换&#xff08;4&#xff09;regexp 正则匹配&#xff08;5&#xff…

操作系统期末复习-内存管理

一、内存管理 分页存储管理&#xff0c;是将一个进程的逻辑地址空间分成若干个大小相等的片&#xff0c;称为页面或页&#xff0c;并为各页加以编号&#xff0c;从0开始&#xff0c;如第0页、第1页等。相应地&#xff0c;也把内存空间分成与页面相同大小的若干个存储块&#xf…

直线追踪

由于项目的需要&#xff0c;最近在做一个直线追踪的东西&#xff0c;但是网上的代码关于车道线或者别的什么之类的直线追踪的代码只是提了一下&#xff0c;相关的代码并不是公开的&#xff0c;所以自己写了一些直线追踪的代码。 代码使用的是kalman滤波进行直线追踪&#xff0…

完美解决labelimg xml转可视化中文乱码问题,不用matplotlib

背景简述 我们有一批标注项目要转可视化&#xff0c;因为之前没有做过&#xff0c;然后网上随意找了一段代码测试完美&#xff08;并没有&#xff09;搞定&#xff0c;开始疯狂标注&#xff0c;当真正要转的时候傻眼了&#xff0c;因为测试的时候用的是英文标签&#xff0c;实…

Sci. Rep. | 一个对任意分子体系实现准确且高效几何深度学习的通用框架

这篇工作是来自纽约城市大学/康奈尔医学院谢磊团队的一篇论文。作者提出了一个通用框架&#xff0c;PAMNet&#xff0c;可以对任意分子体系实现准确且高效的几何深度学习。在小分子性质、RNA三维结构以及蛋白质-配体结合亲和力的预测任务上&#xff0c;PAMNet在准确性和效率方面…

网络编程-认识套接字socket

文章目录 套接字概念端口号网络字节序 套接字类型流套接字数据报套接字 socket常见APIsocket函数bind函数listen函数accept函数connect函数sockaddr结构 套接字概念 socket套接字是进程之间一种通信机制&#xff0c;通过套接字可以在不同进程之间进行数据交流。在TCP/UDP中&…

将html的radio单选框自定义样式为正方形和对号

将html的radio单选框自定义样式为正方形和对号 背景&#xff1a; 如何能把html的<input type"radio" name"option">改成自定义的样式呢&#xff1f;比如想要把他变成正方形&#xff0c;选中的时候是对号。默认的样式太丑了 默认样式&#xff1a; 自…

[数学]三角形的五心之内心

三角形内心的性质 三角形内切圆的圆心称为三角形的内心。内心也是三角形三个角的角平分线的交点 性质1 1.1 设 I I I为 △ A B C △ABC △ABC内一点&#xff0c;则 I I I为 △ A B C △ABC △ABC内心的充要条件是下列条件之一&#xff1a; 1.1.1 I I I到 △ A B C △ABC △…

【C语言】RDMACM、Verbs API与epoll一起使用的示例

一、epoll介绍 epoll是Linux内核为处理大批量文件描述符而作了改进的poll&#xff0c;是Linux下多路复用IO接口select/poll的增强版本&#xff0c;它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。 以下是epoll的主要使用方法和优点&#xff1a; epo…

代码随想录刷题题Day15

刷题的第十五天&#xff0c;希望自己能够不断坚持下去&#xff0c;迎来蜕变。&#x1f600;&#x1f600;&#x1f600; 刷题语言&#xff1a;C Day15 任务 ● 513.找树左下角的值 ● 112. 路径总和 113.路径总和ii ● 106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历…