Linux 内存映射机制(3)
.quad 0x0000000000000000 /* 0x13 reserved */
.quad 0x0000000000000000 /* 0x1b reserved */
.quad 0x0000000000000000 /* 0x20 unused */
.quad 0x0000000000000000 /* 0x28 unused */
.quad 0x0000000000000000 /* 0x33 TLS entry 1 */
.quad 0x0000000000000000 /* 0x3b TLS entry 2 */
.quad 0x0000000000000000 /* 0x43 TLS entry 3 */
.quad 0x0000000000000000 /* 0x4b reserved */
.quad 0x0000000000000000 /* 0x53 reserved */
.quad 0x0000000000000000 /* 0x5b reserved */
.quad 0x00cf9a000000ffff /* 0x60 kernel 4GB code at 0x00000000 */
.quad 0x00cf92000000ffff /* 0x68 kernel 4GB data at 0x00000000 */
.quad 0x00cffa000000ffff /* 0x73 user 4GB code at 0x00000000 */
.quad 0x00cff2000000ffff /* 0x7b user 4GB data at 0x00000000 */
.quad 0x0000000000000000 /* 0x80 TSS descriptor */
.quad 0x0000000000000000 /* 0x88 LDT descriptor */
/* Segments used for calling PnP BIOS */
.quad 0x00c09a0000000000 /* 0x90 32-bit code */
.quad 0x00809a0000000000 /* 0x98 16-bit code */
.quad 0x0080920000000000 /* 0xa0 16-bit data */
.quad 0x0080920000000000 /* 0xa8 16-bit data */
.quad 0x0080920000000000 /* 0xb0 16-bit data */
/*
* The APM segments have byte granularity and their bases
* and limits are set at run time.
*/
.quad 0x00409a0000000000 /* 0xb8 APM CS code */
.quad 0x00009a0000000000 /* 0xc0 APM CS 16 code (16 bit) */
.quad 0x0040920000000000 /* 0xc8 APM DS data */
.quad 0x0000000000000000 /* 0xd0 - unused */
.quad 0x0000000000000000 /* 0xd8 - unused */
.quad 0x0000000000000000 /* 0xe0 - unused */
.quad 0x0000000000000000 /* 0xe8 - unused */
.quad 0x0000000000000000 /* 0xf0 - unused */
.quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */
.quad 0x00cffa000000ffff /* 0x73 user 4GB code at 0x00000000 */
我们把这个值展开成二进制:
0000 0000 1100 1111 1111 1010 0000 0000 0000 0000 0000 0000 1111 1111 1111 1111
根据上述对段描述符表项值的描述, 可以得出如下结论:
B0-B15, B16-B31是0, 表示基地址全为0.
L0-L15, L16-L19是1, 表示段的上限全是0xffff.
G位是1 表示段长度单位均为4KB。
D位是1 表示对段的访问都是32位指令
P位是1 表示段在内存中。
DPL是3 表示特权级是3级
S位是1 表示为代码段或数据段
type为1010 表示代码段, 可读, 可执行, 尚未收到访问
这个描述符指示了段从0地址开始的整个4G虚存空间,逻辑地址直接转换为线性地址。
所以在经过段式映射后就把逻辑地址转换成了线性地址, 这也是在linux中, 为什么逻辑地址等同于线性地址的原因了。
4.3 页式映射分析
现在进入页式映射的过程了, Linux系统中的每个进程都有其自身的页面目录PGD, 指向这个目录的指针保存在每个进程的mm_struct数据结构
中。 每当调度一个进程进入运行的时候,内核都要为即将运行的进程设置好控制寄存器cr3, 而MMU的硬件则总是从cr3中取得指向当前页面目
录的指针。当我们在程序中要转移到地址0x08048368去的时候, 进程正在运行,cr3早以设置好,指向我们这个进程的页面目录了。 先将线性
地址0x08048368展开成二进制:
0000 1000 0000 0100 1000 0011 0110 1000
对照线性地址的格式,可见最高10位为二进制的0000 1000 00, 也就是十进制的32,所以MMU就以32为下标在其页面目录中找到其目录项。这个
目录项的高20位指向一个页面表,CPU在这20位后添上12个0就得到页面表的指针。找到页面表以后, CPU再来看线性地址中的中间10位,
0001001000,即十进制的72.于是CPU就以此为下标在页表中找相应的表项。表项值的高20位指向一个物理内存页面,在后边添上12个0就得到 物
理页面的开始地址。假设物理地址在0x620000的,线性地址的最低12位为0x368. 那么test()函数的入口地址就为0x620000+0x368 = 0x620368
顶(0)
踩(0)
下一篇:linux编译和安装硬件的驱动
- 最新评论