一、PPT相关内容
1.何谓实模式,何谓保护模式?
- 实模式:基地址+偏移量可以直接获得物理地址的模式
- 缺点:非常不安全
- 保护模式:不能直接拿到物理地址
- 需要进行地址转换
- 从80286开始,是现代操作系统的主要模式
2. 什么是选择子?
在计算机体系结构中,特别是在涉及保护模式的操作系统中,选择子是用于指定描述符表(GDT或LDT)中的描述符的索引。选择子包含了几个关键部分:
- 请求特权级(RPL):选择子的低2位表示请求的特权级,决定访问权限。
- 表指示标志(TI):第3位,表示选择的是全局描述符表(GDT,TI=0)还是局部描述符表(LDT,TI=1)。
- 索引:高13位,表示在GDT或LDT中的具体位置,即该表中的偏移量。
选择子是放在段选择寄存器中的16位值,通过它,处理器可以访问描述符表中相应的段描述符,进而获得段的具体信息,如基地址和界限等。
3. 什么是描述符?
描述符是在保护模式下操作系统中使用的一个数据结构,用于定义内存段的属性和访问权限。每个描述符通常存储在全局描述符表(GDT)或局部描述符表(LDT)中。描述符中包含了以下关键信息:
- 基地址(Base Address):段的起始物理地址。
- 段界限(Segment Limit):与基地址相结合,定义了段的大小。这个界限用于限制段内的偏移,确保访问不会超出段的实际物理内存范围。
- 访问权限(Access Rights):描述段的类型(例如,代码段、数据段等)、描述符类型(系统段或代码/数据段)、以及其他访问控制信息(如读/写权限、执行权限)。
- 特权级(DPL, Descriptor Privilege Level):定义了访问该段所需的最低CPU特权级(CPL, Current Privilege Level)。
描述符确保了内存段的保护和正确的访问,是实现多任务和内存保护的基础。通过这些信息,操作系统能够管理不同任务的内存访问权限,防止未授权访问,同时允许合法的访问和操作。
4. 什么是 GDT,什么是 LDT?
GDT(Global Descriptor Table)和LDT(Local Descriptor Table)是在保护模式下使用的两种描述符表,用于定义内存段的属性和访问权限。它们的具体作用和特性如下:
- GDT (Global Descriptor Table):全局描述符表,是全局唯一的。
- 存放一些公用的描述符,和包含各进程局部描述符表首地址的描述符。
- LDT (Local Descriptor Table):局部描述符表,每个进程都可以有一个。
- 存放本进程内使用的描述符。
5. 分别说明 GDTR 和 LDTR
- GDTR (GDT Register):48位寄存器,高32位放置GDT首地址,低16位放置GDT限长
- 限长决定了可寻址的大小,注意低16位放的不是选择子
- LDTR (LDT Register):16位寄存器,放置一个特殊的选择子,用于查找当前进程的LDT首地址。
6. 说明 GDT 直接查找物理地址的具体步骤。
- 给出段选择子(放在段选择寄存器里)+ 偏移量
- 若选择了 GDT 方式,则从 GDTR 获取 GDT 首地址,用段选择子中的13位做偏移,拿到 GDT 中的描述符
- 如果合法且有权限,用描述符中的段首地址加上 1 中的偏移量找到物理地址, 寻址结束
7. 说明通过 LDT 查找物理地址的具体步骤。
- 段选择子读取:首先从程序提供的段选择子开始,这个选择子一般存储在某个段寄存器中(如CS, DS等)。选择子包含两部分重要信息:是否选择GDT(全局描述符表)或LDT(局部描述符表),以及在表中的索引。
- 访问GDT获取LDT描述符:如果段选择子指明选择的是LDT,处理器首先需要访问GDT以获取当前进程的LDT描述符。这是因为每个进程都可以有自己的LDT,但是LDT的起始地址和界限是存储在GDT中的一个特殊的系统段描述符中。
- 获取LDT的首地址:从GDT中获取到的LDT描述符里包含了LDT的首地址。处理器使用这个地址来访问LDT。
- 使用LDT的索引访问段描述符:使用段选择子中的索引来从LDT中获取具体的段描述符。每个段描述符包括基地址、段界限和其他管理属性。
- 计算物理地址:最后,使用段描述符中的段基址加上段内偏移(通常是从程序指令或其他寄存器中给出)来计算出物理地址。如果合法且有权限,用描述符2中的段首地址加上步骤 1 中的偏移量找到物理地址。寻址结束
8. 根目录区大小一定么?扇区号是多少?为什么?
根目录区大小
- 大小设置:
- 在FAT12文件系统中,根目录区的大小是在格式化时预设的。这个大小是由根目录区能够包含的最大条目数决定的,而每个条目通常占用32字节。例如,如果系统允许根目录区包含224个条目,则根目录区的大小将是224 × 32 = 7168字节。
- 计算扇区数:
- 由于扇区通常是512字节,根目录区的大小(以字节为单位)将被512除以得到所需的扇区数。继续上面的例子,7168字节的根目录区将占用7168 / 512 = 14个扇区。
扇区号
- 起始扇区:
- FAT12 文件系统的根目录区紧跟在两个FAT表之后。文件系统的起始部分包括保留扇区(通常包括引导扇区),其后是两个FAT表。
- 根目录的起始扇区号可以通过计算保留扇区和FAT表所占的扇区数来确定。
- 计算方法:
- 假设有一个保留扇区和两个FAT表,每个FAT表大小为9扇区,那么根目录的起始扇区号将是 1(保留扇区)+ 9×2(两个FAT表) = 19。因此,根目录的起始扇区号为19。
9. 数据区第一个簇号是多少?为什么?
在1.44M软盘上,FAT前三个字节的值是固定的0xF0、0xFF、0xFF,用于表示这是一个应用在1.44M软盘上的FAT12文件系统。本来序号为0和1的FAT表项应该对应于簇0和簇1,但是由于这两个表项被设置成了固定值,簇0和簇1就没有存在的意义了,所以数据区就起始于簇2
10. FAT表的作用?
FAT项的值代表文件的下一个簇号
值大于或等于0xFF8,表示当前簇已经是本文件的最后一个簇
值为0xFF7,表示它是一个坏簇
11. 解释静态链接的过程及动态链接的过程
静态链接
- 空间和地址分配
- 一旦所有的符号引用都被解决,链接器将为程序中的各个段(如代码段、数据段)分配内存地址。这包括为函数和全局变量分配地址,这样它们在程序运行时就可以通过这些地址被访问。
- 符号解析和重定位
- 链接器通过查看所有提供的目标文件和库来解析这些符号引用,确保每个被引用的符号都能找到一个明确的定义。
- 链接器将根据它们在最终可执行文件中的位置调整目标文件中的代码和数据。因为在编译时,代码是假设从某个基地址开始的,但是多个代码块放在一起时,实际的起始地址可能不同,因此需要对原始代码中的地址引用进行调整。
动态链接
动态链接器自举
动态链接器本身也是一个不依赖其他共享对象的共享对象,需要完成自举。
装载共享对象
将可执行文件和链接器自身的符号合并成为全局符号表,开始寻找依赖对象。加载对象的过程可以看做图的遍历过程;新的共享对象加载进来后,其符号将合并入全局符号表;加载完毕后,全局符号表将包含进程动态链接所需全部符号。
重定位和初始化
链接器遍历可执行文件和共享对象的重定位表,将它们 GOT/PLT 中每个需要重定位的位置进行修正。完成重定位后,链接器执行 .init 段的代码,进行共享对象特有的初始化过程(例如 C++ 里全局对象的构造函数)。
转交控制权
完成所有工作,将控制权转交给程序的入口开始执行。
12. 静态链接相关PPT中为什么使用ld链接而不是gcc?
避免 gcc 进行 glibc 链接。
13. linux下可执行文件的虚拟地址空间默认从哪里开始分配。
可执行文件的虚拟地址空间默认从 0x08048000
开始分配。这个地址被选中是因为它足够高,可以让程序员容易地识别出指针和数字之间的差别,同时又低足够避免和系统库及内核空间发生冲突。
二、实验相关内容
1. BPB指定字段的含义
1 | typedef struct BPB { |