当前位置: 首页 > news >正文

高端个人网站河北省建设工程安全生产网站

高端个人网站,河北省建设工程安全生产网站,上海网站建设哪家服务好,企业网站教程 优帮云内存寻址 操作系统自身不必完全了解物理内存#xff0c;如今的微处理器包含的硬件线路使内存管理既高效又健壮#xff0c;所以编程错误就不会对该程序之外的内存产生非法访问 x86如何进行芯片级内存寻址Linux如何利用寻址硬件 x86 三种不同的地址术语 逻辑地址 逻辑地址…内存寻址 操作系统自身不必完全了解物理内存如今的微处理器包含的硬件线路使内存管理既高效又健壮所以编程错误就不会对该程序之外的内存产生非法访问 x86如何进行芯片级内存寻址Linux如何利用寻址硬件 x86 三种不同的地址术语 逻辑地址 逻辑地址是机器语言指令中用于表示一个操作数或者指令的地址 不同的机器架构的表现形式不一样80X86的分段结构将每个逻辑地址都由一个段和一个偏移量来组成。 线性地址或称虚拟地址 线性地址是一个32位的无符号整数可以用来表达高达4GB的地址也是程序中实际应用的地址。每个进程都认为自己拥有4GB的地址空间可以使用。范围从0x0000_0000到0xffff_ffff 物理地址 用于内存芯片级内存单元的寻址它们与微处理器的地址引脚发送到内存总线上的电信号对应 转换线路 内存控制单元MMU的分段单元硬件电路将机器语言中的逻辑地址转换成线性地址 分页单元硬件电路将线性地址转换为物理地址 对物理地址的访问也就是对RAM芯片的访问是并发的。多个CPU可以并发地像RAM芯片访问但是由于对RAM芯片的读写是串行的所以同一时间对RAM的读写必须得到仲裁如果发现已经有一个CPU在访问RAM那么此刻到来的其他CPU必须延迟读写操作知道正在读写的那个CPU读写完毕。 这是对于多处理器而言但其实对于单处理器来说也是一样的因为除了单独的那个CPU外访问RAM芯片的还有DMA。 x86模式下的两种模式的不同硬件分段模型 x86的逻辑地址由分段模型提供要有段地址和偏移地址 x86提供了段选择符提供段地址并且为了快速定位到段选择子处理器提供了段寄存器 段选择符的格式 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EXqAsTrr-1677760557953)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230301143659550.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aRXE72qt-1677760557953)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230301145110077.png)] 段寄存器 CS 代码段寄存器 SS 栈段寄存器 DS 数据段寄存器 通常作为数据源端 ES 额外的馈赠 通用目的的段寄存器 通常作为数据目的端 FS 通用目的的段寄存器 GS 通用目的的段寄存器 段描述符格式 每个段由一个8字节的段描述符表示它描述了一个段的所有信息。段描述符全都放在全局描述符表(GDT)或者局部描述符表(LDT)中 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jrYtKt4g-1677760557954)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230301144735619.png)] 根据type字段的不同段描述符可以描述多种不同的段 代码段描述符数据段描述符任务状态段描述符TSS局部描述符表描述符 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6C5kJldU-1677760557954)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230301145029556.png)] 实模式下寻址 x86段寄存器值 4 偏移寄存器值 保护模式下寻址 宏观 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8EziBXOU-1677760557954)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230301145134344.png)] 微观 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YMBLR4Ju-1677760557955)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230301145320158.png)] 2.6版的Linux只有在80X86结构下才使用分段 运行在用户态使用一对相同的段来寻址指令和数据 运行在内核态使用另一对相同的段来寻址指令和数据 不需要给每个任务再单独分配段描述符 内核段描述符和用户段描述符虽然起始线性地址和长度都一样但是DPL不一样 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2NTU6M7I-1677760557955)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230301195021762.png)] (从图中可以看出寻址上限是2^32-1 都从0x0000_0000说明Linux下逻辑地址和线性地址是一致的也就是说逻辑地址的偏移量字段与相应的线性地址的值总是一致的) 段选择符使用宏定义 用户代码段__USER_CS 用户数据段__USER_DS 内核代码段__KERNEL_CS 内核数据段__KERNEL_DS 为了寻址内核代码 CS -- __KERNEL_CS 单处理器使用单个GDT 多出来起使用多个GDT并且使用数组cpu_gdt_table来组织他们 任务状态段TSS每个处理器有1个 每个TSS相应的线性地址空间都是内核数据段相应的线性地址空间的一个小子集 所有的TSS都顺序地存放在init_tss数组的第N个元素 GDT的布局示意图 每个GDT包括18个段描述符和14个空的未使用的保留项 插入未使用的项是为了使经常一起访问的描述符能够处于同一个32Byte的硬件高速缓存中 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zujSOWoG-1677760557955)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230301204842859.png)] Linux在X86的分段机制上运行但是巧妙地绕开了分段Linux主要以分页单元内存管理 分页机制 线性地址翻译成物理地址 其中一个关键任务是将所请求的访问类型与线性地址儿访问全新相比较如果内存访问无效则产生一个缺页异常page fault 线性地址被分成以固定长度为单位的组 -- 页(page) 页内部连续的线性地址被映射到连续的物理连续地址中 物理地址RAM随之被划分成固定长度 -- 页框(page frame) 物理页 记录 线性地址 – 物理地址 映射 关系的数据结构叫 -- 页表(page table) 通过CR0寄存器的PG标志启用分页 PG0则线性地址被解释成物理地址 常规分页 Intel 80386 分页单元处理4KB的页 32位线性地址分成3个域 high10 | mid10 | low12Directory | Table | Offset分级的目的是减少页表每个项PTE所要表达的信息量 如果使用一级页表 2^20个表项 每个表项4字节 需要2^20*4 4MB RAM 每个活动的进程都需要登记在页目录的其中一项 没必要马上为进程的所有页表都分配RAM只有进程实际需要一个页表时才分配给它RAM会更有效率 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qBdpKLqN-1677760557956)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230301214414398.png)] CR3存放页目录所在的物理地址 页目录和页表项的格式 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hi69zt6y-1677760557956)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230302150222919.png)] 每个字段的含义 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZYzUmSXu-1677760557956)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230301215158178.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pa3peMOJ-1677760557957)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230301215207227.png)] 扩展分页 线性地址解释方式变为 High10 | Low22 高10位有效Directory | OFFSET[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f4a6gmfD-1677760557957)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230301215345526.png)] 扩展分页用于将大段的连续的线性地址转换为相应的物理地址 设置CR4处理器的PSE标志 采用混合常规分页与扩展分页 硬件的保护 页表项和页目录项的格式中有USER/SUPERVISOR标志 该标志为0 只有CPL3内核态时可以对页寻址 该标志为1 所有CPL登记都可以对页寻址 常规分页举例 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cIUpJcf8-1677760557958)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230301221529322.png)] 物理地址扩展PAE 物理地址扩展 2^32 -- 2^36 64GB 跟着分页机制也要更改 CR4的PAE标志激活PAE 页目录项中的页大小标志启用大尺寸页 PAE开启时页大小为2MB 改变后的分页机制 64GB的RAM划分为2^24页框 2^36 / 2^24 2^12 4kb 每页还是4K 页表项物理地址字段20bit -- 24bit 12标志位 24物理地址为 以至于原来总大小32bit -- 64bit 引入Page Directory pointer Table PDPT 页目录指针 表 CR3包含27位的PDPT基址字段 映射方式 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-40UZ95Qt-1677760557959)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230302150824664.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6VzIfQTz-1677760557960)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230302150834503.png)] Linux中的分页 Linux提供了一种同时兼容32位和64位系统的普通分页模型 对于32位系统来说 使用两级页表已经足够了 对于64位系统来说 需要更多级的页表 -- 三级甚至四级 2.6.1 采用四级分页模型 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BqDbOxqE-1677760557961)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230302104825732.png)] Linux通过使用页上级目录和页中间目录全为0从根本上取消了页上级目录和页中间目录字段。同样的代码再32位系统下和64位系统下都可以使用 Linux内存管理对进程处理的贡献 每个进程分配一块不同的物理地址空间访问寻址错误区分页面数据组和页面帧主内存中的物理地址。这允许将同一页面存储在页面帧中然后保存到磁盘中然后在其他页面帧中重新加载。 每一个进程有它自己的页全局目录和自己的页表集。当发生进程切换时Linux把cr3控制寄存器的内容保存在前一个执行进程的描述符中然后把下一个要执行进程的描述符的值装入cr3寄存器中。因此当新进程重新开始在CPU上执行时分页单元指向一组正确的页表。 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jZQqxSdU-1677760557961)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230302131738714.png)] Linux中分段分页相关的宏定义 线性地址部分 PAGE_OFFSET 线性地址的offset字段的位数 决定了页大小 X86架构下该宏值为12 #define PAGE_SHIFT 12 #define PAGE_SIZE (_AC(1,UL) PAGE_SHIFT) #define PAGE_MASK ( ~(PAGE_SIZE-1) )#define __AC(X,Y) (X##Y) #define _AC(X,Y) __AC(X,Y) #define _AT(T,X) ((T)(X))PMD_SHIFT 线性地址的offset字段Table字段的总和 #define PMD_SHIFT (PAGE_SHIFT (PAGE_SHIFT-3)) #define PMD_SIZE (1UL PMD_SHIFT) #define PMD_MASK (~(PMD_SIZE-1))PUD_SHIFT 页上级目录项能映射的区域大小的对数 #define PUD_SHIFT 26 #define PTRS_PER_PUD 1 #define PUD_SIZE (1UL PUD_SHIFT) #define PUD_MASK (~(PUD_SIZE - 1)) #define PUE_SIZE 256PDGIR_SHIFT 页全局目录能映射的区域大小的对数 #define PGDIR_SHIFT 26 #define PGDIR_SIZE (1UL PGDIR_SHIFT) #define PGDIR_MASK (~(PGDIR_SIZE - 1)) #define PTRS_PER_PGD 64PTRS_PER_PTE/PTRS_PER_PMD/PTRS_PER_PUD/PTRS_PER_PGD 计算 页表 页中间目录 页上级目录 页全局目录 中表项的个数 禁止PAE 1024 1 1 1024 开启PAE 512 412 1 4 #define PTRS_PER_PTE 4096 #define PTRS_PER_PTE (1UL (PAGE_SHIFT-3)) #define PTRS_PER_PMD (1UL (PAGE_SHIFT-3)) #define PTRS_PER_PGD (1UL (PAGE_SHIFT-3))页表处理相关 /** These are used to make use of C type-checking..*/ typedef struct { unsigned long pte; } pte_t; typedef struct { unsigned long pmd; } pmd_t; typedef struct { unsigned long pud; } pud_t; typedef struct { unsigned long pgd; } pgd_t; #define PTE_MASK PHYSICAL_PAGE_MASKtypedef struct { unsigned long pgprot; } pgprot_t;#define pte_val(x) ((x).pte) #define pmd_val(x) ((x).pmd) #define pud_val(x) ((x).pud) #define pgd_val(x) ((x).pgd) #define pgprot_val(x) ((x).pgprot)#define __pte(x) ((pte_t) { (x) } ) #define __pmd(x) ((pmd_t) { (x) } ) #define __pud(x) ((pud_t) { (x) } ) #define __pgd(x) ((pgd_t) { (x) } ) #define __pgprot(x) ((pgprot_t) { (x) } )修改页表表项 #define pte_none(x) (!pte_val(x)) #define pte_present(x) (pte_val(x) (_PAGE_PRESENT | _PAGE_PROTNONE)) #define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0) static inline void set_pte(pte_t *dst, pte_t val) {pte_val(*dst) pte_val(val); } set_pte_atomic pte_same pte_large 指向大页的检测 pte_bad 页是否存在主存中 pte_preset 页表的present字段设置页标志的函数 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qKpH9Hhe-1677760557962)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230302153749027.png)] 对页表操作的宏 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0DpYFZOh-1677760557963)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230302153833219.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-awMbG7kb-1677760557964)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230302153905375.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IFHHoR4E-1677760557964)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230302153947470.png)] 对页表项操作的宏 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DG9PfamB-1677760557965)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230302154024033.png)] 物理内存布局 内核初始化阶段内核必须简历一个物理地址的映射来指定哪些物理地址范围对于内核是可用的 哪些是不可用的 哪些是映射硬件设备I/O的 哪些是BIOS数据 不可以用的物理地址空间被记录为保留的页框 含有内核代码和已经初始化的数据结构的空间被记录为保留页框 保留页框的页绝不能被动态分配或者交换到磁盘上 作为一般规则Linux内核从物理地址0x00100000开始安装即从第二个兆字节开始安装。所需的页帧总数取决于内核的配置方式。一个典型的配置生成的内核可以在小于3 MB的RAM中加载。 启动过程的早期内核会询问BIOS以获取物理内存的实际大小 新近计算机中内核调用BIOS过程建立一组物理地址范围和其对应的内存类型 内核执行machine_specific_memory_setup() 函数 建立起物理地址映射 BIOS提供的物理地址映射举例 开始结束类型0x0000_00000x0009_ffffUsable0x0010_00000x07fe_ffffUsable0x07ff_00000x07ff_ffff加电自检阶段BIOS写入的硬件设备信息 ACPI data0x07ff_30000x07ff_ffff映射到硬件设备的ROM芯片 ACPI NVS0xffff_00000xffff_ffff由硬件映射到BIOS Reserved 随后执行setup_memory() 函数 分析物理内存区域表示初始化一些变量来描述内核的物理内存 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CFBDdYGw-1677760557965)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230302160256060.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7luthg9w-1677760557965)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230302160350509.png)] 可以在system.map中看到这些图中符号的线性地址它是编译内核以后所创建的 避免kernel被装入一组不连续的页框中Linux跳过RAM的第一个MB _text physical addr 0x00100000 kernel code start _etext kernel code end _etext ~ _edata initialized kernel data _edata ~ _end uninitialized kernel data 图中出现的符号都是编译内核时产生的 进程页表 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-REzRgDLi-1677760557966)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230302161102248.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PzmQe3hE-1677760557966)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230302161612022.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9nSYTOjp-1677760557966)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230302161622170.png)] 内核页表 内核自己维护一组页表放在主内核页全局目录 系统初始化后这组页表从未被任何进程或者任何内核线程直接使用 内核如何初始化自己的页表分两步 实模式下内核创建一个有限的地址空间 128KB大小 装载内核代码段数据段初始页表并用于存放动态数据结构 这个空间只能将内核装到RAM 这个阶段称为临时内核页表内核充分利用剩余的RAM并适当地建立 分页表 假设内核使用的段临时页表和128KB的内存范围能够被RAM的前8MB容纳 分页的第一阶段 要允许实模式下和保护模式下都能够很容易地对这8MB寻址 由于Linux由BIOS加载后起始阶段其实是运行在实模式此时并没有开启分页机制。那Linux在开启分页机制之前需要先做哪些准备工作以支持分页机制答案是页目录项及页表项可以根据x86的硬件分页机制知道此时的两级映射。 一般来说Linux内核安装在RAM中从物理地址0x0010 0000开始的地方也就是说从第二个MB开始。 为什么内核没有安装在RAM第一个MB开始的地方因为PC体系结构有几个独特的地方必须考虑到。例如 页框0由BIOS使用存放加电自检Power-On Self-Test, POST期间检查到的系统硬件配置。物理地址从0x000a 0000到0x000f ffff的范围通常留给BIOS例程并且映ISA图形卡上的内部内存。第一个MB内的其它页框可能由特定计算机模型保留 必须创建映射 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hzk6kyXh-1677760557967)(C:\Users\EDZ\AppData\Roaming\Typora\typora-user-images\image-20230302173829395.png)] 临时页表线性地址0的起始和0xC000_0000的起始都指向同一片物理内存 这个过程的代码 /* page_pde_offset/4 0x300正好为页目录的0x300项(0xc000 0000的前10位) * 0x0000 0000 与 0xC000 0000在页目录项正好偏移0x300项 */ page_pde_offset (__PAGE_OFFSET 20);/* 页表是放在pg0开始的内存处 */movl $(pg0 - __PAGE_OFFSET), %edimovl $(swapper_pg_dir - __PAGE_OFFSET), %edxmovl $0x007, %eax /* 0x007 PRESENTRWUSER */ 10:leal 0x007(%edi),%ecx /* Create PDE entry *//* 填充线性地址0x0000 0000开始的目录项 */movl %ecx,(%edx) /* Store identity PDE entry *//* 填充线性地址0xc000 0000开始的目录项 */movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */addl $4,%edx/* 一个页表包含1024项 */movl $1024, %ecx 11:/* 填充页表项一个页表项映射4k物理内存所以每次加0x1000 */stosladdl $0x1000,%eaxloop 11b/* End condition: we must map up to and including INIT_MAP_BEYOND_END *//* bytes beyond the end of our own page tables; the 0x007 is the attribute bits *//* INIT_MAP_BEYOND_END128*1024, 确定建立的页表是否能够映射“最后一个页表地址” 128K的内存* 如果不行继续建立映射关系 */leal (INIT_MAP_BEYOND_END0x007)(%edi),%ebpcmpl %ebp,%eaxjb 10b 正式启用分页以后 目录中低地址上的页表会被释放 清除 随后 第一阶段就可以通过与物理地址相同的线性地址 或者 通过从0xc0000000开始的8MB线性地址对RAM的前8MB进行寻址 内核通过把swapper_pg_dir所有项都填充为0来创建期望的映射 // swapper_pg_dir这个全局变量在汇编 head.S 中定义了 // 编译时便被分配了这是一个真正的全局变量生命周期与内核相等 ENTRY(swapper_pg_dir).fill 1024,4,0临时的页面全局目录包含在swapper_pg_dir变量中。临时页面表从pg0开始存储就在内核未初始化的数据段结束图2-13中的符号_end之后。 启用分页单元 /** Enable paging*/movl $swapper_pg_dir-__PAGE_OFFSET,%eaxmovl %eax,%cr3 /* set the page table pointer.. */movl %cr0,%eaxorl $0x80000000,%eaxmovl %eax,%cr0 /* ..and set paging (PG) bit */ 最终映射的建立 建立完临时映射大概8M的内存空间后Linux内核就运行在保护模式了此时就可以开始进行一些内核的基本初始化工作了。 最终内核页表的初始化主要是这个函数在 x86 上大概分了几种情况 内存小于 896M内存小于 4G内存大于 4G 主要都是在 init.c - paging_init() 这个函数里实现的。 在这个函数里会通过预定义在配置环节的宏定义、CPU的寄存器值等条件完成不同情况的区分。 在这里我们不需要太纠结于Linux中页表之间的层次关系比如觉得pgd一定要索引到pud其实pud,pmd及pte只是Linux中对页表的一个抽象只是一个命名而已应该关注的是里面的内容比如说常规分页模式下pgd的目录项是初始化为pte的基地址及一些标志位虽然没有pud但是能找到下一级页表就行。下面我们从代码实现中就能看到 函数的调用关系为pagetable_init - kernel_physical_mapping_init void __init paging_init(void) // line: 499 static void __init pagetable_init (void) // line310 static void __init kernel_physical_mapping_init(pgd_t *pgd_base) // line: 143 static void __init page_table_range_init (unsigned long start, unsigned long end, pgd_t *pgd_base) // line: 10 static void __init pagetable_init (void) {unsigned long vaddr;pgd_t *pgd_base swapper_pg_dir;#ifdef CONFIG_X86_PAEint i;/* Init entries of the first-level page table to the zero page *//* 在扩展模式下pgd的前三项映射线性地址空间为0-3G这为用户空间访问的地址范围所以用一个空页对它进行初始化 */for (i 0; i PTRS_PER_PGD; i)set_pgd(pgd_base i, __pgd(__pa(empty_zero_page) | _PAGE_PRESENT)); #endif/* Enable PSE if available */if (cpu_has_pse) {set_in_cr4(X86_CR4_PSE);}/* Enable PGE if available */if (cpu_has_pge) {set_in_cr4(X86_CR4_PGE);__PAGE_KERNEL | _PAGE_GLOBAL;__PAGE_KERNEL_EXEC | _PAGE_GLOBAL;}kernel_physical_mapping_init(pgd_base);remap_numa_kva();/** Fixed mappings, only the page table structure has to be* created - mappings will be set by set_fixmap():*/vaddr __fix_to_virt(__end_of_fixed_addresses - 1) PMD_MASK;page_table_range_init(vaddr, 0, pgd_base);permanent_kmaps_init(pgd_base);#ifdef CONFIG_X86_PAE/** Add low memory identity-mappings - SMP needs it when* starting up on an AP from real-mode. In the non-PAE* case we already have these mappings through head.S.* All user-space mappings are explicitly cleared after* SMP startup.*/pgd_base[0] pgd_base[USER_PTRS_PER_PGD]; #endif }/** This maps the physical memory to kernel virtual address space, a total * of max_low_pfn pages, by creating page tables starting from address * PAGE_OFFSET.*/ // pfn 应该是 page frame number static void __init kernel_physical_mapping_init(pgd_t *pgd_base) {unsigned long pfn;pgd_t *pgd;pmd_t *pmd;pte_t *pte;int pgd_idx, pmd_idx, pte_ofs;pgd_idx pgd_index(PAGE_OFFSET); // 0xC000_0000 对应的页全局目录项在页全局目录中对应的位置pgd pgd_base pgd_idx; // 页全局目录的一个结构体指针指向的是页全局目录数组的某个元素pfn 0;for (; pgd_idx PTRS_PER_PGD; pgd, pgd_idx) { // 页全局目录中有 1024 个元素遍历一遍pmd one_md_table_init(pgd); // 最后返回的是一个 pmd_t *但是在二级分页的情况下pmd 就等于 pgdif (pfn max_low_pfn)continue;for (pmd_idx 0; pmd_idx PTRS_PER_PMD pfn max_low_pfn; pmd, pmd_idx) { // 二级分页下PTRS_PER_PMD 为1所以这个循环体只会被执行一次unsigned int address pfn * PAGE_SIZE PAGE_OFFSET; // 这个明显是 PA和 pfn 相关的应该都是 PA/* Map with big pages if possible, otherwise create normal page tables. */if (cpu_has_pse) { // 如果支持大页表也就是一页 4M反正内核是需要连续空间并且也不会被换出所以使用大页表是合理的unsigned int address2 (pfn PTRS_PER_PTE - 1) * PAGE_SIZE PAGE_OFFSET PAGE_SIZE-1;// 不启用 PAE 的话下面这两个 if 分支实际上是等价的// set_pmd 执行的是一个把值赋给指针的操作// 值物理地址左移12位标志位// 指针页中间目录数组中的某个元素指针note that二级分页的情况下页中间目录项页全局目录项if (is_kernel_text(address) || is_kernel_text(address2))set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC));elseset_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));pfn PTRS_PER_PTE;} else { // 如果不支持大页表页就是一页只能是 4k那么需要把页中间目录中的每个页表项都初始化一遍所以需要另一个循环pte one_page_table_init(pmd);for (pte_ofs 0; pte_ofs PTRS_PER_PTE pfn max_low_pfn; pte, pfn, pte_ofs) {// set_pte 的操作和 set_pmd 类似if (is_kernel_text(address))set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));elseset_pte(pte, pfn_pte(pfn, PAGE_KERNEL));}}}} }当建立完内核最终的线性映射之后线性地址0xc0000000 - 0xc0000000896M, 对应的物理地址就为0x00000000-0x00000000896M这就是所谓的线性映射。
http://www.w-s-a.com/news/273878/

相关文章:

  • 漳州网站建设公司推荐wordpress更改主机
  • c2c商城网站建设方案英文网站注册
  • 电子商务网站的运营一般需要做哪些准备宣传片拍摄思路
  • 网站建设网页制作百度怎么做自己网站
  • 建设设计网站公司巴州建设局网站
  • 淘宝建设网站的好处韶关市网站建设招标
  • 佛山高端网站免费招聘网站建设
  • 申请网站就是做网站吗wordpress tag 优化
  • 建站系统排行榜菏泽机关建设网站
  • 网站群建设费用科技通信网站模板下载
  • 网站开发的流程是怎样的自己做自媒体在哪个网站比较好
  • 网站的html代码在哪网页线上开发制作
  • 免费商用自媒体图片网站做网站好的公司有哪些
  • 阿雷网站建设公司中国建筑考试网官网首页
  • 厦门网站制作网页无法跳转到建设银行网站
  • 怎么建设自己网站简述网页布局的几种方法
  • 软文营销文案100篇如何优化搜索引擎的搜索功能
  • 做网站创意杭州家具网站建设方案
  • 福州seo网站推广优化乐清建网站
  • 莆田cms建站模板简述网站设计流程
  • 班级网站建设组织机构建设注册中心网站首页
  • 即墨网站建设地址怎么在文档中做网站一点就开
  • 做网站联系方式互联网行业分析
  • 杭州网站建设索q479185700高淳网站建设
  • 有什么做任务拿钱的网站精准的搜索引擎优化
  • 洛阳有建社网站的吗电力建设工程质量监督总网站
  • 网站404报错热水器网站建设 中企动力
  • 网站降权恢复淘宝 网站建设
  • 安州区建设局网站台州优秀关键词优化
  • 网站假设教程湖南微信管理系统