php语言做的大网站,互联网网站设计,网站多语言模块,网站页面图片尺寸进程#xff08;4#xff09;——进程地址空间【linux】 一.什么是进程地址空间二.进程地址空间不是真实地址#xff1f;三.物理地址与进程地址空间的关系#xff08;整体部分#xff09;四. 细节4.1 进程地址空间的本质#xff1a;4.2 为什么要有进程地址空间#xff1… 进程4——进程地址空间【linux】 一.什么是进程地址空间二.进程地址空间不是真实地址三.物理地址与进程地址空间的关系整体部分四. 细节4.1 进程地址空间的本质4.2 为什么要有进程地址空间i. 具体应用ii. 宏观好处 4.3 页表i. 权限位ii. 标志位 一.什么是进程地址空间
地址空间按照我们的现有的理解来说。
可以说成这样
这里可以算是我们的现有的对地址空间的认识 内存分区不同的变量存储在进不同的区中
但是今天要告诉大家这个进程地址空间不是真正的地址空间
接下来就开始进行验证
二.进程地址空间不是真实地址
子进程和父进程的值进行全局变量修改后 值不一样但是全局变量地址却是一样的
这说明了打印出来的变量的地址不是真正的物理地址
#includestdio.h
#includeunistd.h
int i0;
//定义全局变量 i
int main(){size_t ifork();if(i0){//分别让子进程和父进程打印地址i的值和地址//并且全都让i重新赋值i10;while(1){sleep(1);printf(i am father,val%d ptr%p\n,i,i);}}else{i100;while(1){sleep(1);printf(i am child,val%d ptr%p\n,i,i);}}}
接下来就用这个代码践行测试一下 这里能惊奇的发现 父进程和子进程中的变量i值全都不同但是它们的地址全都一样
这个结果就证明了地址空间指向的肯定不是真实物理内存。
如果是地址指向真实的物理内存那这样的情况肯定是不存在的内存中的一个空间内不可能存在一个变量有两个值的情况。
那真实的情况是什么样的
记下来就带来物理地址和地址空间之间的大致关系
三.物理地址与进程地址空间的关系整体部分
这里我们就用一幅图来代表这其中的大致关系 这里只是大致表示它的逻辑关系其中细节没有补足 这里是地址空间都是虚拟地址 真实地址是真实的存储区域 页表则是记录了虚拟地址对应的真实物理地址 充当了地址空间和真实内存中间的媒介。
现在我们就可以来思考一下 上面这个代码为什么运行结果是这样
因为地址一样并不指的是真实物理内存的地址 而是地址空间的虚拟地址
上面这个问题就是写实拷贝。 大致过程就是这样了 实际物理内存这两个是不同的 但是虚拟地址是一样的。
大致过程是这样了但是接下来我们就来补充一些细节
四. 细节
4.1 进程地址空间的本质
这里有个细节我们以前都叫做内存地址空间 但是现在改成了进程地址空间 这说明了现在这个地址空间是属于进程的
什么叫属于进程 在我们之前讲解进程的时候 提到了进程是由 进程task_struct代码和数据 组成的
这里提到进程地址空间同样属于进程
所以我们这里需要更正一下我们对进程的理解了 进程内核数据结构task_struct mm_struct 页表结构代码和数据
这个mm_struct就是进程地址空间
那这里也就能确定 进程地址空间是用来进行内存可视化的数据结构同样也能被系统进行管理同样符合和进程PCB一样的先描述再组织
所以每个进程pcb创建时同样也要创建属于他们的虚拟内存——mm_struct
4.2 为什么要有进程地址空间
我们这里讲完了进程地址空间是啥玩意后 接下来就要来讲讲为什么要有它
i. 具体应用
这里我们来举一个小例子 我们在前面讲过进程有独立性 每个进程不知道别的进程的存在它们只管自己的进程申请和使用
每个进程有了进程地址空间后 就能记录下每个进程的空间范围用来方便申请内存 同时不妨碍 只要每个类中有一个起始和结束的地址 这样就不会互相冲突更好维护进程的独立性
这里只是个具体的实际应用
接下来就讲宏观上的整体作用了
ii. 宏观好处
1. 进程地址空间相当于进程和物理地址间加了个媒介 可以让进程在进行寻址请求或者申请时进行审查所以一旦访问异常直接拦截 使关于进程的内存操作简单方便了很多。
2. 因为有地址空间和页表的存在将进程管理模板和内存管理模板进行解耦合
这里通俗的讲就是
当我们用户进行进程的创建和使用的时候。 不再需要关心内存的申请和创建操作系统自己就会去调用 让使用计算机的门槛和难度降低了很多
4.3 页表
这里提个小细节 还记得之前提过在切换进程的时候cpu中存储的是进程的上下文。
页表就存在寄存器中算是进程的上下文的一部分
i. 权限位
mm_struct中进行了分区。 分为了常量区和代码区。 其中的代码都是不能进行更改的 这里我们能猜到其实这个 不能进行更改肯定不是真实的物理内存进行的权限划分 而是进程地址空间实施的。
因为如果真实物理地址进行权限划分的话 那在常量区数据最开始怎么进行写入 所以权限的划分是体现在进程地址空间中的
那代码是如何知道什么权限有没有被划分的
这里就要牵扯到页表了
页表中有一个专门的权限位 用来表示地址指向的空间是否具有对应的权限
ii. 标志位
还记得我们讲进程的时候提到过进程挂起的这个概念
当进程长时间未使用或者资源没有准备时 系统会将该进程的代码和数据从内存中去掉让其他进程使用内存资源
那如何知道进程有没有被挂起本质是问系统如何知道代码和数据是否在内存中读取 这里我们就要提一下 系统为了防止空间和时间的浪费所以页表中使用的是惰性加载 就是说会将进程的代码和数据先读取在进程内存地址空间而不去使用实际内存的空间 就是说会在地址空间处先占个位置在实际内存中不会先去开辟空间
所以为了让系统知道什么地址被成功加载到了物理内存中 页表又加了一个标志位
用来专门标识数据和代码是否被加载到了内存空间当中 这样就可以做到进程的挂起和惰性加载了。
如果当操作系统发现进程的代码和数据没有被加载到实际内存中时会触发缺页中断将进程暂停重新将进程的代码和数据从磁盘加载到内存中然后再继续执行。 前面我们提到的写实拷贝同样也是缺页中断的功能实现。