Marvell(美满科技)半导体IC芯片全系列-亿配芯城-从内存布局图角度看内存管理
你的位置:Marvell(美满科技)半导体IC芯片全系列-亿配芯城 > 芯片资讯 > 从内存布局图角度看内存管理
从内存布局图角度看内存管理
发布日期:2024-01-09 12:12     点击次数:106

我们知道Linux是分为两种状态 用户态和内核态,Linux内核需要跑在硬件平台上,硬件平台也有自己的状态。这里还是ARMARM有其中处理器的模式。

用户模式(user):用户程序运行的模式。系统模式(system):特权模式。一般中断模式(IRQ):普通中断模式。快速中断模式(FIQ):快速中断模式。管理模式(supervisor):操作系统的内核通常运行在该模式下。数据访问终止模式(abort):当数据或者指令预取终止时进入该模式,用于虚拟存储及存储保护。未定义指令模式(undefined):当未定义的指令执行时进入该模式,可用于支持硬件协处理器的软件仿真。

Linux内核的用户态和内核态两种模式分别对应的用户模式和管理模式。

这里还是以32位,对应4GB,内核一般内核:用户按照1:3的比例分配。这也是可以修改的。

我们知道分页机制,赋予了每个进程都有寻址4GB的空间,因为每个进程都有自己的进程表。

内核空间是从3GB开始,lowmem这段空间其实就是我们常说的线性映射区。(为啥虚拟地址明明在高位却是low,继续看)所谓的线性映射区,就是物理内存线性地映射到这段内核空间的区域中。在 ARM32 平台上,物理地址[0:760MB]的这一部分内存被线性映射到[3GB :3GB+760MB]的虚拟地址上(因为其物理地址在低位)。

线性映射区的虚拟地址和物理地址相差PAGE_OFFSET,即3GB。内核中有相关的宏来实现线性映射区的虚拟地址到物理地址的查找,例如pa(x)和va(x)。

其中,__pa()把线性映射区的虚拟地址转换为物理地址,转换公式很简单,即用虚拟地址减去PAGE_OFFSET(3GB),然后加上PHYS_OFFSET(这个值在有的ARM平台上为0,在ARM Vexpress平台上为0x6000_0000)。

物理内存被分成了两部分,低端的部分用在线性映射区,线性映射区就是这里的“lowmem”区域。剩下的高端部分的物理内存被称为高端内存(High Memory),内核要使用它,必须通过高端映射的方式来访问。

内核通常把低于760MB的物理内存称为线性映射内存(Normal Memory), 电子元器件采购网 而高于760MB以上的称为高端内存。 (这个高端是针对内核内存来说,780到1G)

这个分给内核的1G分成了高端和线性。

高端780到1G是干啥呢?剩下的264MB虚拟地址空间是保留给vmalloc机制、fixmap和高端异常向量表等使用的。内核很多驱动使用vmalloc机制来分配连续虚拟地址的内存,因为有的驱动不需要连续物理地址的内存;除此以外,vmalloc机制还可以用于高端内存的临时映射。一个32位的系统中,实际支持的内存数量会超过内核线性映射的长度,但是内核要具有对所有内存的寻找能力。

(这里我想的是虽然在内核,但是我内核还是要对整个内存有个控制能力,这里就是体现,在vmalloc机制就可以干这个:个人看法,有纠正的大佬在评论区告诉小的一下)

编译器在编译目标文件并且链接完成之后,就可以知道内核映像文件最终的大小,接下来将其打包成二进制文件,该操作由arch/arm/kernel/vmlinux.ld.S 控制,其中也划定了内核的内存布局。

内核image本身占据的内存空间从_text段到_end段,并分为如下几个段。text段:_text和_etext为代码段的起始和结束地址,包含了编译后的内核代码。init段:init_begin和init_end为init段的起始和结束地址,包含了大部分内核模块初始化的数据。data段:_sdata和_edata为数据段的起始和结束地址,保存大部分内核的已初始化的变量。BSS段:bss_start和bss_stop为BSS段的开始和结束地址,包含初始化为0的所有静态全局变量。

上述几个段的大小在编译链接时根据内核配置来确定,因为每种配置的代码段和数据段长度都不相同,这取决于要编译哪些内核模块,但是起始地址_text 总是相同的。内核编译完成之后,会生成一个System.map文件,查询这个文件可以找到这些符号的具体数值。



相关资讯