首先,一个32位系统具有0xffffffff
(4'294'967'295
)线性地址以访问RAM顶部的物理位置。
内核将这些地址划分为用户空间和内核空间。
用户空间(高内存)可以由用户访问,必要时还可以由内核访问。
地址范围以十六进制和十进制表示:
0x00000000 - 0xbfffffff
0 - 3'221'225'471
内核空间(低内存)只能由内核访问。
地址范围以十六进制和十进制表示:
0xc0000000 - 0xffffffff
3'221'225'472 - 4'294'967'295
像这样:
0x00000000 0xc0000000 0xffffffff
| | |
+------------------------+----------+
| User | Kernel |
| space | space |
+------------------------+----------+
因此,您看到的内存布局dmesg
与内核空间中线性地址的映射相对应。
首先,.text,.data和.init序列提供内核自己的页表的初始化(将线性转换为物理地址)。
.text : 0xc0400000 - 0xc071ae6a (3179 kB)
内核代码所在的范围。
.data : 0xc071ae6a - 0xc08feb78 (1935 kB)
内核数据段所在的范围。
.init : 0xc0906000 - 0xc0973000 ( 436 kB)
内核的初始页表所在的范围。
(对于某些动态数据结构,另外为128 kB。)
这个最小的地址空间刚好足以将内核安装在RAM中并初始化其核心数据结构。
它们的使用大小显示在括号内,例如内核代码:
0xc071ae6a - 0xc0400000 = 31AE6A
用十进制表示法是3'255'914
(3179 kB)。
二,初始化后内核空间的使用
lowmem : 0xc0000000 - 0xf77fe000 ( 887 MB)
内核可以使用lowmem范围直接访问物理地址。
这不是完整的1 GB,因为内核始终至少需要128 MB的线性地址才能实现非连续的内存分配和固定映射的线性地址。
vmalloc : 0xf7ffe000 - 0xff7fe000 ( 120 MB)
虚拟内存分配可以基于非连续方案分配页面帧。这种模式的主要优点是避免了外部碎片,该碎片用于交换区域,内核模块或为某些I / O设备分配缓冲区。
pkmap : 0xff800000 - 0xffa00000 (2048 kB)
永久内核映射允许内核建立高内存页面帧到内核地址空间的持久映射。使用kmap()映射HIGHMEM页面时,将从此处分配虚拟地址。
fixmap : 0xffc57000 - 0xfffff000 (3744 kB)
这些是固定映射的线性地址,可以引用RAM中的任何物理地址,而不仅仅是像lowmem地址这样的最后1 GB。固定映射的线性地址比他们的lowmem和pkmap同事更有效率。为固定映射分配了专用的页面表描述符,并且从此处分配了使用kmap_atomic的HIGHMEM页面的映射。
如果您想更深入地研究兔子:
理解Linux内核