Linux操作系统——深度剖析进程地址空间

14 篇文章 0 订阅
12 篇文章 0 订阅

前言

C/C++的程序地址空间就是如图所示,栈区是往低地址方向增长的。栈区和堆区是相向而生的。
子进程中对val进行修改,会发生写时拷贝。从而拷贝一份数据到另外的地方,变量的值是不一样的,但是两个变量对应的地址却是一样的,说明这个地址不是真正的物理地址,而是虚拟地址。
在这里插入图片描述


一、进程的地址空间是什么?

实际上是一个结构体,里面存放了一个进程不同分区的虚拟地址空间。(不是真实的物理空间)
每个进程都有一个地址空间,那么操作系统要管理,所以要先描述后管理,所以为每个进程定义一个mm_struct存放该进程的地址空间(里面有各个分区的起始和结束位置,总大小等)。
因为这个进程地址空间是属于这个进程的,在进程的task_struct里面会存放指针指向这个mm_struct,通过task_struct可以找到mm_struct


二、mm_struct内部有什么?

代码如下(示例):有代码段,常量区,堆区,栈区的起始位置和结束位置等信息。
虽然这里只有start和end,但是每个进程都认为mm_struct代表整个内存,且所有的地址都是0x00 00 00 00 (1共1字节)到0xFF FF FF FF,这些地址也就是虚拟地址。
每个进程都认为地址空间的划分是按照4GB空间划分的(即每个进程都认为自己有4GB的空间)但是实际上物理内存可能只有1G

struct mm_struct
{
	unsigned int code_start;
	unsigned int code_end;
 
	unsigned int init_data_start;
	unsigned int init_data_end;
 
	unsigned int uninit_data_start;
	unsigned int uninit_data_end;
 
	unsigned int heap_start;
	unsigned int heap_end;
	//......
}

三.虚拟地址空间与物理内存如何关联

mm_struct相当于描绘了一个4GB的虚拟地址空间,里面对应的地址叫做虚拟地址。(mm_struct内部并不是真的有这么大的地址空间,而是用起始位置和结束位置来表示的)
那么物理地址和虚拟地址如何映射到一起的呢? ————使用页表+MMU(一种硬件,称为内存管理单元,用于查找页表,一般集成在CPU中)

页表

页表是操作系统为每个进程维护的一张表,存放着虚拟地址和物理地址(就像hash表),用于根据虚拟地址去找到对应的物理地址。(将虚拟地址映射到对应的物理地址)
在这里插入图片描述


设计进程地址空间的重要性

原因一:操作系统可以对进程进行风险管理(权限管理),保证物理内存数据安全
如果进程直接访问物理内存的话,无法保证物理内存中的数据安全,通过添加一层软件层,操作系统可以完成有效的对进程操作内存进行风险管理(权限管理)(比如通过页表转地址,你有没有权限访问这个区域里面的内容,有没有越界访问等),本质目的是为了保护物理内存以及各个进程的数据安全!
你虚拟地址转换成物理地址的时候,是交给操作系统来转的,它就可以决定帮不帮你转,转完以后你有没有权限可以访问。

原因二:屏蔽内存申请内存的过程,将普通进程读写内存和OS对内存进行管理在软件层面上进行解耦
在OS角度,如果空间立马给你,意味着整个系统会有一部分空间,本来可以给别人立马用的,现在却可能被你闲置着,造成了空间浪费。
一开始进程申请了空间的时候,操作系统并不会马上将物理空间分配给进程,而是给进程划分了一片虚拟内存空间(比如在mm_struct中将heap_end+100),当进程真正要读取这段空间的时候,操作系统说等等(缺页中断),然后为进程开辟一片物理空间给进程使用(基于缺页中断进行物理内存申请)。

原因三:不同进程中每个区域的相对位置比较确定,CPU可以以统一的视角看待内存;程序的代码数据可以加载到物理内存的任意位置

如果没有进程的地址空间,CPU没法以统一的方式去寻找每个进程的起始位置。


为什么子进程修改值以后,地址还是相同?
因为这个地址是虚拟地址,子进程和父进程中这个变量的物理地址是不相同的。
子进程的创建是以父进程为模板的,所以子进程的进程地址空间和页表也是继承的父进程的,所以g_val的虚拟地址都是一样的。
子进程修改了g_val的值以后,发生了写时拷贝,为子进程重新开辟了一块物理空间,将父进程g_val的值拷贝进入这个物理空间,然后修改子进程页表中原来g_val的虚拟地址和物理地址的映射关系,将物理地址改为新开辟内存的地址。但是此时虚拟地址没有发生变化,从而也就发生了这种情况。
代码共享一份的实现也很简单,只要将父进程和子进程页表中存放代码的虚拟地址映射到同一块物理空间即可。
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值