概述
进程地址空间
- 认识地址空间
- 什么是地址空间
- 映射机制
- 拓展内容
在开始之前,先强调两个重要的概念:
1.一个独立的逻辑控制流,它提供一个假象,好像我们的处理器独占地使用处理器
2.一个私有的地址空间,它提供一个假象,好像我们的程序独占地使用内存系统
不理解这个没关系,当看完这篇文章,就会恍然大悟。
认识地址空间
之前在学习C语言的时候,总是会提到堆区,栈区,静态区这些概念,好像我们的内存就是按照这些区域划分的,但实际是这样吗?
当程序创建了两个不同的进程,在创建之前的代码中在常量区开辟一个值,创建进程完成之后,让子进程对这个值进行修改,修改之后让父子进程分别对这个值的地址和数值大小进行打印。然后就会发现一个从来没见过的现象:打印出来的地址是相同的,但是值却不同。
所以只有一个可能,就是这两个值本质上被存放在了内存的不同区域,那么为什么他们的地址却是相同的呢?结论就是这个这个常量区的值存放的地址不是物理内存的地址,而是虚拟地址。所以几乎所有的语言,如果它有“地址”的概念,这个地址一定不是物理地址,而是虚拟地址。
这里有个注意的地方:
堆的生长方向和栈的生长方向是相反的,上面粘贴了一张在堆区连续申请空间的地址截图,可以发现,堆区的空间的申请并不是连续的,这是因为多余出来的空间需要记录本次申请的堆空间的属性,叫做cookie数据,这样当使用free释放空间的时候就会精确知道要释放哪块空间了。
字符串本质上也是存放在正文代码中的,在正文代码中有一个字符常量区用于存放这些字符。
什么是地址空间
联系文章最开始的的两个关键结论,地址空间本质上就是操作系统为进程画的大饼,目的是为了让每个进程都认为自己独占地使用内存系统。
地址空间是一种内核数据结构,它里面至少要有各个区域的划分
struct addr_room
{
int code_start;
int code_end;
int init_start;
int init_end;
int uninit_start;
int uninit_start;
int heap_start;
int heap_end;
int stack_start;
int stack_end;
//...
};
地址空间就是像上面一样的数据结构,那么对地址空间的调整本质上就是对begin和end的调整。
可以发现,地址空间本质上也是一种数据结构,所以对地址空间的管理也是对数据结构的操作,本质上也是“先描述,再组织”
那为什么不直接使用物理内存当作地址空间呢?
如果直接使用物理内存,首先是会出现访问越界的问题,如果访问了不该访问的地址空间,会造成极其不安全的后果,;如果进程过多,还会导致内存碎片的问题。
映射机制
那么虚拟的地址空间是如何将空间中的内容映射到真实的物理内存中呢?
是通过页表进行映射的:
进程的PCB结构体中有一个指针指向虚拟地址空间的结构体(指针如图所示),然后通过页表将虚拟地址空间中的内容映射到物理内存中。
拓展内容
不知道大家有没有想过一个问题,代码被加载到内存中之后,是如判断每行代码每个变量是开辟在哪个空间的呢?
- 我们写的程序在编译形成可执行程序的时候,没有被加载到内存中的时候,程序的内部其实就已经有地址了。
- 地址空间不仅是操作系统内部要遵守,编译器内部也要遵守,编译器编译代码的时候,就已经给我们形成了各个区域,并且采用了和Linux一样的编址方式,为每一行代码,每一个变量都进行了编址
- 程序的内部地址,依旧采用编译器编译好的虚拟地址,当程序加载到内存的时候,每行代码每个变量就具有了一个地址。
具体的页表中的实现,这里不做更多的解释说明。
最后
以上就是聪慧小霸王为你收集整理的进程地址空间认识地址空间什么是地址空间的全部内容,希望文章能够帮你解决进程地址空间认识地址空间什么是地址空间所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复