花钱买不到系列—linux虚拟地址空间-CSDN博客https://blog.csdn.net/weixin_49529507/article/details/141272458?spm=1001.2014.3001.5501 在上一篇文章中,引出了虚拟地址这块,也用大富翁给儿子们画饼的例子解释,通过大富翁的例子,也知道了进程觉得自己是独占内存的,上一篇最后一个话题,操作系统如何给进程画的饼。
比如你在公司上班,老板给你画饼,完成这个项目就提升你为经理,或者说拿下这个订单你就是销售主管。可能老板不止对你一个人这样说,可能对其他人也这样说,公司上市后给您多少股份?所以老板要不要记住给每一个员工画的饼?肯定要呀,不然到时候就会搞出大乌龙,所以老板就在自己的小本本里面记着。
所以操作系统也一样,给每一个进程,都画了大饼,进程都觉得自己独占了内存。所以操作做系统也要记着这些饼,所以还是之前的一个理念,"先描述,后组织"。
所以老板的小本本里面就是描述,对谁? 目标?什么职位?多少钱?描述起来,所以在老板的小本里面,就是有一个struct 蓝图。方便管理。
所以,操作系统里面有那么多的进程,进程要被管理,那地址控制要不要被管理?肯定的,所以地址空间的本质:就是内核的一种数据 mm_struct,跟pcb一样,要被管理。它是我们进程的地质空间的描述的最核心的结构。
接下来,是如何给进程画大饼的啊?
可是我看到这个地址空间,那么它上面是有各个区域的,有代码区。已初始化数据区未初始化数据区,堆区还有栈区,它有这么多的区域的话,它是一个内核的数据结构。那么它是一个内核的数据结构的话,那么我最关心的就是这个数据结构里面的成员有哪些,先不关心和进程是怎么关联起来的,对里面的成员感兴趣
开始聊之前来确定一下共识,所以我们来聊聊这个地址
那么地址,比如0x00000000~0xffffffff,这些编号有什么意义,其实没什么,地址最大的意义,只要保证唯一性就可以了。
我们要表示2的32次方个地址。怎么做到我们能够有2的32个次方地址?而且彼此之间还不重复呢啊,其实我们要表示它的地址。我们用32位的数据即可啊,也就是说呢,我们32位的数据32个比特位就可以了。那么为什么呢?因为任何一个比特位,它的一个那么要么为零,要么为1。所以32位的那么比特位,它的排列组合的个数就是二的32次方。从全0到全1,排列,这个就叫编址。
可是我们常识告诉我们地址空间上面呢,有各种各样区域啊,这什么堆区栈区?那么,请问这些区域我该怎么去理解呢?操作系统要管理这个地址空间,它必须先描述再组织,而且还要保证这上面的各个区域都是有的,是怎么做到的,下面来了解一下。
不知道大家有没有这样的经历,小学的时候基本是男女混坐的,你是一个小女生,你非常讨厌你的同桌,你就在桌子上面上面画了一根线,假设桌子100cm。小女孩警告小男孩别越界。
所以这个时候男孩子的桌子的范围是[1,50],小女孩的范围就是[51,100],所以她的区域就划分好了,那么其中这个女孩所做的在桌子上划分的三八线的这个过程,我们把它可以称之为这就叫做区域划分啊。不要因为各种区域很复杂其实很简单,就类型这样。画一根线就可以了,换成计算机的表达就是下图这个样子。默认100cm。 这就叫做区域的划分。
有一天,小男孩和女孩说,我每次越界你就打我,有时候我不是故意的呀,后面女孩子觉得也有道理,做出了改变,重新划分,每个人让出5cm,作为缓冲区,到缓冲区不理你,超过缓冲区就打你。
那计算机如何调整。所以调整就是对它的start和end做调整就可以了
后来 , 小男孩天天欺负小女孩,然后小女孩就把缓冲区给取消了,直接个30小男孩,超过就直接打你。所以重新划分,所以小女孩的区域就增大了
所以在计算机里面就类似于下面这样。所以应一个区域有多个数字,每一个数字都是代表着桌子的一个位置。
上面的这些啊code_start code_end,它就叫做区域的起始地址。我们称之为叫做区域的。好,那么两个区域中间部分,那么就有无数个地址可以被我们对应的,那么用户所使用了。这一部分区域之间的这无数个地址,包括我们每个区域的地址,我们都称之为叫做虚拟地址
这个代码区啊,我自己编好成了,代码区加载到内存代码区,它占多少大小?它是固定的。因为代码区不会被调整啊,以初始化未初始化全局数据区,它也是固定的,它不会变化。但是,堆区和栈区不一样,它是可以不断的。我去malloc调整我的大小栈区呢,它也可以不断入栈。我们定局部变量,在函数内定义变量等等。我们的堆栈之间的区域也不断在做调整呀,那么所以堆栈之间啊,那么其中堆栈之间,它们的区域做调整,所谓的区域调整啊,本质就是修改啊,那么各个区域的。的end或者是我们的start啊。
这个地址空间就是操作系统给进程画的大饼,让进程觉得自己独占4g内存空间,所以进程需要记得操作系统画的饼,就像员工也会记着老板画的饼,所以进程pcb里面有一个指针指向mm_struct,方便使用。