热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

x86从实际模式到保护模式(3):强大的分页机制

x86从实模式到保护模式虚拟内存和用户程序结构物理内存的分页原因开启分页机制自我综述验证分页机制,强大如斯,理论和物理,分离让你脑子停熄虚

x86从实模式到保护模式

          • 虚拟内存和用户程序结构
          • 物理内存的分页原因
          • 开启分页机制
          • 自我综述
          • 验证


分页机制,强大如斯,理论和物理,分离让你脑子停熄


虚拟内存和用户程序结构

虚拟内存在理论上可以看作是一个用户程序拥有自己的一块4G内存,即该用户程序认为自己独占所有内存,而物理上则是高速缓存存储器(cache)根据局部性原理进行数据交换,加上流水线技术等等的一种假象,虚拟内存的地址是一种逻辑地址,是根据段式存储而分配的一种逻辑上的线性内存空间,如果不进行分页,则就是物理地址,否则还是要通过页部件转换成物理地址,在此不做过多叙述。

用户程序分为:全局部分(GDT,PCB,MBR,HMA,Stack segment,Kernel…)+ 任务的私有部分(LDT,TSS,Code segment,Data segment,Stack segment)。所有的用户程序的全局部分几乎是一样的。

物理内存的分页原因

物理内存分页的原因:

把虚拟内存对应于物理内存进行分页,页的大小为4K,物理内存一共有1024 * 1024个页(内存为4G),由物理地址00000000开始,每次加上4K即00001000,以此类推。

在这里插入图片描述
段地址转化成页地址的过程:取段地址的前20位*4找到页表中对应的索引的值(该值是物理地址的前20位)+ 线性地址的后12位 = 32位物理地址,将内容写入页中即可

为了让用户程序的两部分在页中也泾渭分明,因此在内存中必须先定义全局部分的页,因此产生了页目录表和页表

页表有1024个页表的物理地址,每个页表有1024个物理页,因此可以表示1024 * 1024个页

CR3(页目录基址寄存器)存放着当前任务的页目录地址,因此相应的页部件也得调整:

线性地址的前10位用来指明页目录的索引(CR3指向页目录),根据索引的值取得页表的地址,中间10位取得页表的索引的值,加上最后的12位合成32位物理页。

;创建系统内核的页目录表PDT;页目录表清零 mov ecx,1024 ;1024个目录项mov ebx,0x00020000 ;页目录的物理地址xor esi,esi.b1:mov dword [es:ebx+esi],0x00000000 ;页目录表项清零 add esi,4loop .b1

此处要搞清楚,是先有内核才有页表的,但是内核后期也要页表,因此内核的页表在映射的过程中是直接把线性地址转化成物理地址即可。

页表和页目录表结构

  • 21~31:页表物理基地址
  • 0:P,页表和页目录表是否在内存中
  • 1:RW,页表和页目录表是否可读写
  • 2:US,用户或管理位,特权级位
  • 3:PWT,页级通写位,是否写入高速缓存
  • 4:PCD,页级高速缓存位
  • 5:A,是否被访问
  • 6:D,是否写过数据
  • 7:O(页目录表);PAT(页表项):页属性表支持位
  • 8:G,全局位,该表是否为全局位
  • 9~11:程序是否可使用

;在页目录内创建指向页目录自己的目录项mov dword [es:ebx+4092],0x00020003 ;在页目录内创建与线性地址0x00000000对应的目录项mov dword [es:ebx+0],0x00021003 ;写入目录项(页表的物理地址和属性) ;创建与上面那个目录项相对应的页表,初始化页表项 mov ebx,0x00021000 ;页表的物理地址xor eax,eax ;起始页的物理地址 xor esi,esi.b2: mov edx,eaxor edx,0x00000003 mov [es:ebx+esi*4],edx ;登记页的物理地址add eax,0x1000 ;下一个相邻页的物理地址 inc esicmp esi,256 ;仅低端1MB内存对应的页才是有效的 jl .b2.b3: ;其余的页表项置为无效mov dword [es:ebx+esi*4],0x00000000 inc esicmp esi,1024jl .b3

开启分页机制

CR3:指向页目录,CR0的PG位表示开启分页机制

;令CR3寄存器指向页目录,并正式开启页功能 mov eax,0x00020000 ;PCD=PWT=0mov cr3,eaxmov eax,cr0or eax,0x80000000mov cr0,eax ;开启分页机制

页表建立的先后是,先把用户程序放入虚拟内存,然后搜寻物理内存的空闲页将其地址放入建立的页表


用户程序的页表是怎么来的?是先复制内核的页目录,将高端映射为内核部分,低端映射为用户任务部分

空闲页的搜索
页映射位串:操作系统会在获得内存信息的时候会获得所有页的相关信息,当有程序要分配内存时,就在位串中来指定每个页的分配情况,共1024 * 1024个b

搜索位串是否空闲

bts r, r

刷新TLB:传统情况下,程序要使用内存,必须经过页目录表和页表转化成物理地址,因此把页表项预先装在处理器中,可以加快速度,这个叫做TLB(转换速查缓存器,快表)

mov cr3, ebx
mov ebx, cr3

在这里插入图片描述

tlb较小,当tlb满的时候,替换掉那些用的少的行


自我综述

一篇文章想讲全分页机制肯定是不可能的,想完全弄懂只能去看源码和理论和物理上的实现,这点很绕,但是不可避免。
虚拟内存说白了其实就是个虚拟的玩意,是程序自己想的,你可以想象程序的所有段其实都在硬盘上。打个比方,一个.c文件生成.out文件里面的地址其实都是虚拟地址,而这个地址是他自封的,他认为他在运行的时候也是这个地址
当程序变成一个进程的时候他会将线性地址(虚拟地址)通过页目录表和页表映射到内存中,当发生切换进程的时候,旧的进程会将页目录表的信息存放在CR3寄存器,这个新的进程也会通过页目录表和页表得到物理页,如果物理页都被占用了,则将暂时不用的物理页先换出内存(cache或者其他技术)。

验证

// 01.c
#include int main() {printf("Hello World! \n");return 0;
}

gcc 01.c # 编译源代码
readelf -a a.out

# 查看该用户程序头
lh@lh-virtual-machine:~$ readelf -a a.out
ELF 头:# 魔数,其中45 4c 46对应的是ASCII表值是ELF,表明这个文件是一个elf文件Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 ....入口点地址: 0x1060程序头起点: 64 (bytes into file)Start of section headers: 14712 (bytes into file)标志: 0x0Size of this header: 64 (bytes)Size of program headers: 56 (bytes)# 标号的数量Number of program headers: 13Size of section headers: 64 (bytes)# 段的数量Number of section headers: 31

好了,x86从实模式到保护模式到此结束啦,下一阶段我要走业务了,所以先学一学protobuf和libevent空间吧!


推荐阅读
  • Android 构建基础流程详解
    Android 构建基础流程详解 ... [详细]
  • 基于Linux开源VOIP系统LinPhone[四]
    ****************************************************************************************** ... [详细]
  • 深入解析C语言中结构体的内存对齐机制及其优化方法
    为了提高CPU访问效率,C语言中的结构体成员在内存中遵循特定的对齐规则。本文详细解析了这些对齐机制,并探讨了如何通过合理的布局和编译器选项来优化结构体的内存使用,从而提升程序性能。 ... [详细]
  • 为了在Hadoop 2.7.2中实现对Snappy压缩和解压功能的原生支持,本文详细介绍了如何重新编译Hadoop源代码,并优化其Native编译过程。通过这一优化,可以显著提升数据处理的效率和性能。此外,还探讨了编译过程中可能遇到的问题及其解决方案,为用户提供了一套完整的操作指南。 ... [详细]
  • 在C语言程序开发中,调试和错误分析是确保代码正确性和效率的关键步骤。本文通过一个简单的递归函数示例,详细介绍了如何编写和调试C语言程序。具体而言,我们将创建一个名为 `factorial.c` 的文件,实现计算阶乘的功能,并通过逐步调试来分析和解决可能出现的错误。此外,文章还探讨了常见的调试工具和技术,如GDB和断点设置,以帮助开发者高效地定位和修复问题。 ... [详细]
  • 本文详细介绍了在Linux系统上编译安装MySQL 5.5源码的步骤。首先,通过Yum安装必要的依赖软件包,如GCC、GCC-C++等,确保编译环境的完备。接着,下载并解压MySQL 5.5的源码包,配置编译选项,进行编译和安装。最后,完成安装后,进行基本的配置和启动测试,确保MySQL服务正常运行。 ... [详细]
  • 在64位Linux系统上编译GCC时,可能会遇到一个错误,即在构建共享库过程中,`.libs/alloc.o` 文件中的重定位 `R_X86_64_32` 无法应用于 `.rodata.str1.8` 段。这一问题通常与目标文件的地址空间限制有关,需要通过调整编译选项或修改源代码来解决。具体来说,可以尝试使用 `-fPIC` 选项以生成位置无关代码,或者检查相关对象文件的链接方式。 ... [详细]
  • 在CentOS上部署并使用FFmpeg多媒体处理工具
    最近在进行音频处理时需要用到FFmpeg,本文将详细介绍如何在CentOS系统上部署并使用这一强大的多媒体处理工具。首先,从官方网站下载FFmpeg的最新版本,然后通过Xftp工具将下载的压缩包(如ffmpeg-4.3.1.tar.xz)传输到服务器上。接下来,解压文件并按照官方文档进行编译安装。安装完成后,可以通过命令行工具验证FFmpeg是否成功安装,并开始进行多媒体文件的转换和处理。此外,文章还将介绍一些常用的FFmpeg命令和参数,帮助用户快速上手。 ... [详细]
  • 本文详细介绍了在DS-5开发工作室中集成最新编译器工具链的方法与步骤。通过逐步指导,帮助用户高效地配置和使用最新的编译器,以提升开发效率和代码质量。此外,还提供了常见问题的解决方案和最佳实践建议,确保用户能够顺利进行开发环境的升级。 ... [详细]
  • 在腾讯云服务器上部署Nginx的详细指南中,首先需要确保安装必要的依赖包。如果这些依赖包已安装,可直接跳过此步骤。具体命令包括 `yum -y install gcc gcc-c++ wget net-tools pcre-devel zlib-devel`。接下来,本文将详细介绍如何下载、编译和配置Nginx,以确保其在腾讯云服务器上顺利运行。此外,还将提供一些优化建议,帮助用户提升Nginx的性能和安全性。 ... [详细]
  • 如何利用正则表达式(regexp)实现高效的模式匹配?本文探讨了正则表达式在编程中的应用,并分析了一个示例程序中存在的问题。通过具体的代码示例,指出该程序在定义和使用正则表达式时的不当之处,旨在帮助读者更好地理解和应用正则表达式技术。 ... [详细]
  • 在 Windows 10 环境中,通过配置 Visual Studio Code (VSCode) 实现基于 Windows Subsystem for Linux (WSL) 的 C++ 开发,并启用智能代码提示功能。具体步骤包括安装 VSCode 及其相关插件,如 CCIntelliSense、TabNine 和 BracketPairColorizer,确保在 WSL 中顺利进行开发工作。此外,还详细介绍了如何在 Windows 10 中启用和配置 WSL,以实现无缝的跨平台开发体验。 ... [详细]
  • GDB 使用心得与技巧总结
    在使用 GDB 进行调试时,可以采用以下技巧提升效率:1. 通过设置 `set print pretty on` 来美化打印输出,使数据结构更加易读;2. 掌握常见数据结构的打印方法,如链表、树等;3. 利用 `info locals` 命令查看当前作用域内的所有局部变量;4. 在需要进行类型强制转换时,正确使用语法,例如 `p (Test::A *) pObj`。这些技巧能够显著提高调试的便捷性和准确性。 ... [详细]
  • 深入解析 ELF 文件格式与静态链接技术
    本文详细探讨了ELF文件格式及其在静态链接过程中的应用。在C/C++代码转化为可执行文件的过程中,需经过预处理、编译、汇编和链接等关键步骤。最终生成的可执行文件不仅包含系统可识别的机器码,还遵循了严格的文件结构规范,以确保其在操作系统中的正确加载和执行。 ... [详细]
  • 在CentOS上部署和配置FreeSWITCH
    在CentOS系统上部署和配置FreeSWITCH的过程涉及多个步骤。本文详细介绍了从源代码安装FreeSWITCH的方法,包括必要的依赖项安装、编译和配置过程。此外,还提供了常见的配置选项和故障排除技巧,帮助用户顺利完成部署并确保系统的稳定运行。 ... [详细]
author-avatar
0519bobo_724
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有