操作系统问答二
PPT相关内容
什么是实模式,什么是保护模式
- 实模式就是用基地址加偏移量就可以直接拿到物理地址的模式
- 保护模式就是不能直接拿到物理地址的模式
什么是选择子
- 选择子共16位,放在段选择寄存器里
- 低2位表示请求特权级
- 第3位表示选择GDT方式还是LDT方式
- 高13位表示在描述符表中的偏移(故描述符表的项数最多是2的 13次方)
什么是描述符
BASE:段基址,由上图的两部分(BASE 31-24和 BASE 23-16)
G:LIMIT的单位,该位0表示单位是字节,1表示单位是4KB
D/B:该位是0表示这是一个16位的段,1表示这是一个32位段
AVL:该位是用户位,可以被用户自由使用
LIMIT:段的界限,单位由G位决定,数值上(经过单位换算后的值)等于段的长度
P:段存在位,该位为0表示该段不存在,为1表示存在
DPL:段权限
S:该位为1表示这是一个数据段或者代码段,为0表示这是一个系统段(比如调用门,中断门等)
TYPE:根据S位的结果,再次对段类型进行细分
其中,段界限表示段边界的扩张最值,即最大扩展多少或最小扩展多少,用20位来表示,它的单位可以是字节,也可以是4KB,这是由G位决定的(G为1时表示单位为4KB)。
实际段界限边界值=(描述符中的段界限+1)*(段界限的单位大小(即字节或4KB))-1,如果偏移地址超过了段界限,CPU会抛出异常。
全局描述符表位于内存中,需要用专门的寄存器指向它后, CPU 才知道它在哪里。这个专门的寄存器便是GDTR(一个48位的寄存器),专门用来存储 GDT 的内存地址及大小。
什么是GDT,什么是LDT
- GDT:全局描述符表,是全局唯一的。存放一些公用的描述符、 和包含各进程局部描述符表首地址的描述符。
- LDT:局部描述符表,每个进程都可以有一个。存放本进程内使 用的描述符。
请分别说明GDTR和LDTR的结构
- GDTR:48位寄存器,高32位放置GDT首地址,低16位放置GDT 限长(限长决定了可寻址的大小,注意低16位放的不是选择子)
- LDTR:16位寄存器,放置一个特殊的选择子,用于查找当前进 程的LDT首地址。
请说明GDT直接查找物理地址的具体步骤
- 给出段选择子(放在段选择寄存器里)+偏移量
- 若选择了GDT方式,则从GDTR获取GDT首地址,用段选择 子中的13位做偏移,拿到GDT中的描述符
- 如果合法且有权限,用描述符中的段首地址加上(1)中的 偏移量找到物理地址。寻址结束
请说明通过LDT查找物理地址的具体步骤
- 给出段选择子(放在段选择寄存器中)+偏移量
- 若选择了LDT方式,则从GDTR获取GDT首地址,用LDTR 中的偏移量做偏移,拿到GDT中的描述符1
- 从描述符1中获取LDT首地址,用段选择子中的13位做偏移, 拿到LDT中的描述符2
- 如果合法且有权限,用描述符2中的段首地址加上(1)中 的偏移量找到物理地址。寻址结束。
根目录区大小一定吗?扇区号是多少?为什么?
- 不一定,通过BPB_RootEntCnt(根目录文件数的最大值,比如0xE0)来计算根目录的大小,具体计算公式是
- 根目录区占用扇区数 = RootDirSectors = (BPB_RootEntCnt*32(一个目录项占32个字节))/BPB_BytesPerSec(一个扇区的字节数,比如512)
- 典型值:19
数据区第一个簇号是多少?为什么
- 起始簇号是2
- 在 1.44M 软盘上,FAT 前三个字节的值必须是固定的,分别是 0xF0、0xFF、0xFF,用于表示这是一个应用在 1.44M 软盘上的 FAT12 文件系统。本来序号为 0 和 1 的 FAT 表项应该对应于簇 0 和簇 1,但是由于这两个表项被设置成了固定值,簇 0 和簇 1 就没有存在的意义了。
FAT表的作用
文件分配表被划分为紧密排列的若干个表项,每个表项都与数据区中的一个簇相对应,而且表项的序号也是与簇号一一对应的。用于寻找下一个簇号
解释静态链接的过程
静态链接是由链接器在链接时将库的内容加入到可执行程序中的做法。
在编译 main.c 的时候,编译器还不知道 printf 函数的地址,所以在编译阶段只是将一个“临时地址”放到目标文件中,在链接阶段,这个“临时地址”将被修正为正确的地址,这个过程叫重定位。所以链接器还要知道该目标文件中哪些符号需要重定位,这些信息是放在了重定位表中。
在链接的时候,我们需要告诉链接器需要链接的目标文件和库文件(默认 gcc 会把标准库作为链接器输入的一部分)。链接器会根据输入的目标文件从库文件中提取需要目标文件。
知道了这些信息后,链接器就可以开始工作了,分为两个步骤:
1)合并相似段,把所有需要链接的目标文件的相似段放在可执行文件的对应段中。
2)重定位符号使得目标文件能正确调用到其他目标文件提供的函数。
解释动态链接的过程
所谓动态链接就是在运行的时候再去链接。从动态库的角度来看,动态库像普通的可执行文件一样,有其代码段和数据段。为了使得动态库在内存中只有一份,需要做到不管动态库装载到什么位置,都不需要修改动态库中代码段的内容,从而实现动态库中代码段的共享。而数据段中的内容需要做到进程间的隔离,因此必须是私有的,也就是每个进程都有一份。因此,动态库的做法是把代码段中变化的部分放到数据段中去,这样代码段中剩下的就是不变的内容,就可以装载到虚拟内存的任何位置。那代码段中变化的内容是什么,主要包括了对外部函数和变量的引用。
动态库是把地址相关的内容放到了数据段中来实现地址无关的代码,从而使得动态库能被多个进程共享。
动态链接生成的可执行文件运行前,系统会首先将动态链接库加载到内存中。当所有的库都被加载进来以后,类似于静态链接,动态链接器从各个动态库中可以知道每个库都提供什么函数(符号表)和哪些函数引用需要重定位(重定位表),然后修正.got 和.got.plt 中的符号到正确的地址,完成之后就可以将控制权交给可执行文件的入口地址,从而开始执行我们编写的代码了。
静态链接相关PPT中为什么使用ld链接而不是gcc
用 gcc 的话有可能去调 C 库,使程序环境变得复杂,所以用 ld
gcc会自动链接操作系统的库,有时我们并不想这么操作。ld就老实多了,只会链接参数中所规定的。
Linux下可执行文件的虚拟地址空间默认从哪里开始
linux 下,ELF 可执行文件默认从地址 0x08048000 开始分配
实验相关内容
BPB指定字段的含义
如何进入子目录并输出
如何获得指定文件的内容,即如何获得数据区的内容
如何进行C代码和汇编之间的参数传递和返回值传递
汇编代码中对I/O的处理方式,说明指定寄存器所存值的含义