7.3. 进程虚拟地址空间和页大小

龙芯架构参考手册指出,应用软件可访问的内存物理地址空间范围为0~2PALEN-1。在LA32架构下,PALEN理论上是不大于32的正整数,通常建议取32;在LA64架构下,PALEN理论上是不大于64的正整数,具体取值由实现决定,通常位于[40,48]范围内。应用软件可以执行CPUCFG指令,读取0x1号配置字中的PALEN域,从而确定PALEN的具体值。龙芯3A5000处理器采用LA64架构,PALEN为48,因此支持的物理地址空间范围是0~248-1。如果程序中的访存指令地址超出该范围,就会触发异常。

现在,除实时操作系统、嵌入式系统等对处理速度和内存大小有严格要求的场景可能直接使用物理地址外,复杂操作系统通常不会让程序直接访问物理内存,而是使用虚拟地址空间。存储管理部件(Memory Management Unit,MMU)负责把虚拟地址转换为物理地址,并对软件隐藏物理地址细节,使多个进程能够安全、并行地共享系统物理内存。每个进程都有独立的虚拟地址空间,该空间会被划分为多个区域进行管理。图6-4展示了一个典型C语言程序运行时的用户态虚拟内存布局。

一个典型的C语言程序运行时的用户态虚拟内存布局

一个典型进程至少包含代码段、数据段、栈空间、共享库和堆区等区域;动态链接进程还可以在运行时创建更多段空间。不同段区域的数据占用一个或多个内存页,并具有不同访问权限。例如,代码段所在页通常具有读和执行权限,数据段通常具有读写权限。在LoongArch架构下,程序加载到虚拟内存的起始地址通常为0x1C0000000,0x000000000~0x1C0000000范围内的地址为预留地址。

内存地址空间按页(Page)组织。页是Linux系统进行内存管理的基本单位。不同系统的页大小可能不同,取决于处理器、MMU和系统配置。可以使用下面命令查看当前系统页大小:

$ getconf PAGE_SIZE
4096

getconf显示当前系统页大小为4096字节,即4KB。程序加载到内存时,小于4KB的段会被放入一个内存页;大于4KB的段则会占用两个或多个连续内存页。