实验四Linuxx86-64内存分页机制分析.docx
实验四Linux X86-64内存分页机制分析实验1 .掌握Linux X86-64模式下内存分页机制;2 .掌握Linux操作系统虚拟内存的基本原理;3 . 了解Linux内核模块加载方法;4 .为后续操作系统内核实验做准备。二、实验环境及要求1 .在完成实验一、实验二和实验三的基础上完本钱实验;2 .本实验要求学生在自己安装的Ubuntul8.4 AMD64操作系统上完成。三、实验内容与步骤1 .系统安装(1) 在 Windows 下安装虚拟机软件 VMware Workstation ;(2)下载并安装在虚拟机中。2 .从github上下载本实验所需的软件并编译;(1) git clone#软件下载在当前目录的jingrep。目录下(2 ) tar -xvf #解包(3 ) make #在解包生成的目录下生成可执行文件编译成功后生成(1)两个内核模块文件:modules/sys_reg/sys_和 modules/phy_mem/phy_(2 )两个应 用程序 :apps/running-prog/running-prog 和 apps/read-phy- mem/read-phy-mem3 .安装内核模块文件(1) sudo insmod moduIes/sys_reg/sys_(2 ) sudo insmod modules/phy_mem/phy_4 .分页机制分析请仔细阅读附录A ,参照操作过程,深入分析X86-64的分页机制,把变量a的线性地 址转换为物理地址,并读取该物理地址单元的值,观察和running-prog的输出是否一致。四、实验结果在实验报告的这个模块中撰写操作过程的结果,并做出适当的分析。五、实验小结包括:实验过程遇到的问题及解决过程,对本次实验的认识、心得。1.前言本文分析Linux在X86-64模式下的虚拟内存映射流程。讨论的平台是X86-64,也可以称为AMD64 ,IA-32e,是现在广泛使用的64位架构, 可以向前兼容16位和32位的x860另外一种独立的64位架构IA-64与现有架构不同而 且开展不好,比方,安腾(Itanium)处理器,一般是接触不到的。我们平常讨论的64位基本 就是指x86-64o图1是IA-32e两种运行模式。根据处理器强大的兼容性,我们可以配置 为long mode和legacy mode,根据安装的操作系统的模式可以使用不同的模式。Operating modes editOperating modeOperating sub-modeOperating system requiredType of code being runDefault address sizeLong mode64-bit mode64-blt operating system or boot loader64-blt code64 bitsCompatibility mode64-blt operating system or boot loader32-blt protected mode code32 bits64-blt operating system16-blt protected mode code16 bitsLegacy modeProtected mode32-blt operating system or boot loader, or 64-blt boot loader32-blt protected mode code32 bits16-bit protected mode operating system or boot loader, or 32- or 64-blt boot loader16-bit protected mode code16 bitsVirtual 8086 mode16- or 32-bit protected mode operating system16-bit real mode code16 bitsReal mode16-blt real mode operating system or boot loader, or 32- or 64-blt boot loader16-blt real mode code16 bits图L IA-32e两种运行模式从图1可以看出,我们下面要测试的是Operating mode = Long mode , Operating sub-mode = 64-bit mode下的虚拟内存映射流程。1)映射流程简述分段的存在更多就是为了兼容性,在X86-64下的Linux对于分段机制近似于绕过不 用。所以我们下面就不讨论逻辑地址到线性地址的转换了,因为每个段的基址为0 ,经过运 算后线性地址和逻辑地址是一样的。32-bit的操作系统进程空间是232字节,即4GBo但是,64-bit的操作系统并没有提 供264字节的空间,这受限于处理器的线性地址宽度。当前X86-64的CPU实际的线性地 址宽度是48-bit,能提供248字节的进程空间。当前IA-32e架构的CPU地址总线的最大 宽度是52-bit,分页过程就是把48-bit的线性地址转换为不超过52-bit的物理地址。在X86-64模式下,48-bit线性地址有以下3种映射分配模式。(1) 4-KByte 页面Linear Address4739 3830 2921 2012 110I I ED IPML4Directory PtrDirectoryTableOffset当页面大小是4KB时,采用4级页表来组织分页系统。分别是:第一级:PML4 ( Page-Map Level-4 ,四级页表)第二级:PDPT ( page-directory-pointer table ,页目录指针表)第三级:PD ( Page Directory ,页目录)第四级:PT ( Page Table ,页表)(2 ) 2-MByte 页面Linear Address 4739 3830 2921 200PML4Directory PtrDirectoryOffset当页面大小是2MB时,采用3级页表来组织分页系统。(3 ) 1-GByte 页面Linear Address 4739 3830 290PML4Directory PtrOffset当页面大小是1GB时,采用2级页表来组织分页系统。2)分页表项结构我们暂时还不知道Linux使用哪种分页,但是知道了每种模式下各个寄存器和page structure entry 的格式,如图 2 所示(原表见 Intel 64 and IA-32 Architectures Software Developer's Manual, Vol3, 4.4 % 可以一步一步分析。b3b2b10598756b5453521M1M-1i2J1J02827262524232221201918171615141312111 09876543210Reserved2Address of PML4 TableIgnoredPC DPTIgn.CR3IgnoredRsvd.Address of page-directory-pointer tableIgn.RsVC1 g nAPC DPTUR w1PMl4e: presentIgnored0RML46: not presentX0IgnoredRsvd.Address of 1GB page frameReservedPATIgn.G1DAPC DPTURw1PDPTE: 1GB pageA0IgnoredRsvd.Address of page directoryIgn.01 g nAP C DPTU /SR / VJ1PDPTe: page directoryIgnored0PDTPE: not presentA0IgnoredRsvd.Address of 2MB page frameReservedPATIgn.G1DAP C DP卜jTURw1pde: 2MB pageADIgnoredRsvd.Address of page tableIgn.01 g nAP C DP TuRW1PDE: 麒Ignored0pde: not presentXDIgnoredRsvd.Address of 4KB page frameIgn.GPATDAPC DPTuRW1pre: 4KB pageIgnored0PTE: not presentFigure 4-11. Formats of CR3 and Paging-Structure Entries with IA-32e Paging图2. IA-32e分页表项结构说明:M is an abbreviation for MAXPHYADDR, which is at most 52; M 表示的是 物理地址总线位宽,比方说36位,那么M=36 ,即最大的物理内存空间是64G。2.验证过程1)编译加载编译文件,加载sys_z phy_模块。2)运彳亍 running-prog3456789101112B(程序running-prog中有代码段:1 int a;int main()a = 0xA5A5AA550000FFFF;printf (= %1XZ addr: %p nr, a t &a);print_sys_reg_inf o ();whilell)(" 一 sleep (100);) return 0;在程序中给变量a赋值,输出变量a的线性地址,第6行通过内核模块sys一读取当前一些特殊寄存器的值,然后处于休眠状态。运行后可以得到以下输出。jjdubuntu:*/mytest/jingrepo/slv64$ ./apps/running-prog/running-prog a = A5A5AA550000FFFF, addr: 0x55818fedc018 Control Registers CR0 = 0x80050033 CR0.PG = 1 CR4 = 0X606F0 CR4.PAE = 1 cr3 = 0X3142CO01 CR3 PT Base = 6x3142(:。按照 Intel® 64 and IA-32 Architectures Software Developer1 s Manual 的 P2890 说明,如果=1/ = 1, and IA32_ = 1, 4-level paging is used.也就是工作再 IA-32e 模 式下(64位模式X给变量a赋了个特殊值方便确认,由于演示的操作系统和running-prog都是64位 的,所以对a的地址翻译是遵循X86-64机制。程序输出的0x55818fedc018是a的逻辑 地址,也就是a的线性地址。我们先把48bit的线性地址按照4-KByte页面格式分段。Linear Address4739 3830 2921 2012 110PML4Directory PtrDirectoryTableOffsetI I ED I16进制的线性地址:2 进制的线|生地址:0 0001 1 0,00 1111 111, 0 1101 1100 ,0000 0001 10004739, 3830, 29-21, 2012, 11-0Oxab, 0x6, 0x7fz Oxdc, 0x183)运行sudo read-phy-mem读取物理内存该命令从物理内存中读取指定长度的字节,需要sudo权限运行,格式是:sudo read-phy-mem物理地址长度(1)访问PML4 ( Page-M叩Level-4 ,四级页表)控制寄存器CR3存储的是PML4的基址0x3142c000线性地址bits47-39的值是PML4E 在PML4中的偏移量,计算出的 PML4E (即PML4 Entry )地址为: 0x3142c000+0xab*8=0x3142c558 ,从该处读取 16 字节。jjdubuntu:*/mytest/jtngrepo/slv64$ sudo ./apps/read-phy-mem/read-phy-mem 0x3142c558 16 sudo password for jjd: rst = 3142C558read from Ox3142c558, size 160X3142C558:3392f067 800000000X3142C560:00000000 00000000(2)访问页目录指针表(Page Directory Pointer Table , PDPT )PDPT的基址为0x3392f000,线性地址bits 3830的值是PDPTR即PDPT项在PDPT 中偏移量,计算出的PDPTE地址为:0x3392f000+0x6*8=0x3392f030 ,从该处读取16jjdubuntu:*/mytest/jingrepo/slv64$ sudo ./apps/read -phy-mem/read-phy-mem 0x3392f030 16 sudo password for jjd: rst = 3392fO30read from Ox3392F030, size 160X3392F03O:778ea067 00000000OX3392F038:00000000 00000000PDPTE表项的值是Ox 778ea067 z bit7=0 ,说明该项指向的是Page Directory (即页框的大小是4KB或2MB ,不是1GB )。(3)访问页录(Page Directory , PD )PD的基址为0x778ea000z线性地址bits 29-21的值是PDE (即PD项)在PD中的偏 移量,计算出PDE地址是:0x778ea000 + 0x7f* 8 = 0x778ea3f8 ,从该处读取16字节。jjdubuntu:/mytest/jingrepo/slv64$ sudo ./apps/read-phy-mem/read-phy-mem 0x778ea3f8 16 rst = 778ea3f8read from 0x778EA3F8, size 160X778EA3F8:744f2067 00000000OX778EA4O0:4d2a0067 00000000PDPTE表项的值是Ox 744F2067 , bit7二0 ,说明该项指向的是Page Table (即页框的 大小是4KB ,不是或2MB)。(4)访问页表(Page Table f PT)PT的基址为0x744f2000,线性地址bits 20 -12的值是PTE(即PT项)在PT中偏移量,计算出PTE的地址为:0x744f2000 + Oxdc * 8 = 0x744f26e0 ,从该处读取16字节。jjdubuntu:-/mytest/ji.ngrepo/slv64$ sudo ./apps/read-phy-mem/read-phy-mem 0x744f26e0 16 rst = 744f26e0read from 0X744F26E0, size 160X744F26E0:lb660867 800000000X744F26E8:00000000 00000000(5)访问页框(Page Frame )变量a所在的页框的基址为Ox 16660000,线性地址bits 11-0为变量a在页框内的偏移 量,计算变量a的物理地址为:0xlb660000 + 0x18 = 0xlb660018 ,从该处读取16字 节。.jjdubuntu:*/mytest/jingrepo/slv64$ sudo /apps/read-phy-mem/read-phy-mem 0xlb66 0018 16Irst = lb660018read from 0X1B660018, size 160X1B660018:0000ffff a5d5dd550X1B660O20:00000000 00000000jjdubuntu:*/mytest/jtngrepo/slv64$ |物理地址开始0X1B660018开始的8个字节是OxA5A5AA550000FFFF ,和应用程序 running-prog 的输出一致。附录原文参照: