未完待续
本文整理自清华ucore os课程以及实验。博主以前并不系统的学习过os,这一次使用更加系统的方式和笔记来学习os,本文是笔记部分。
实验可以访问:操作系统获取
启动、中断、异常和系统调用
启动(如何从实模式进入保护模式?)
前两天一个学长问我如何进入保护模式的,我支支吾吾就说了一下寻址方式的改变和bios加电如何如何,真的令人汗颜,我觉得我不配说看过《从实模式到保护模式》那本书。现在趁着系统学习操作系统的这个机会,我也应该把保护模式的启动好好学习记忆一下了。
- CS(左移四位+IP) EIP 决定了启动的地址,通过实模式寻址
- 第一条指令是长跳转指令,跳转到Bios代码中执行,bios进行底层初始化的工作
- 之后bios加载磁盘或者硬盘的第一个主引导扇区,读入内存中(0x7c00)去,使得可以执行扇区中的代码
- 第一个扇区中的代码会完成后续的加载工作,这个扇区被称为bootloader
- bootloader 首先使能保护模式(CR031位置1),自动加载段机制(建立全局描述符表GDT)。之后读取ucore代码,将cs:EIP的值指向ucore的入口点。
- 保护模式的寻址方式:段寄存器中有一个段选择子,index(高13位)。index 会查找段描述符表,找到的段描述符包含着起始地址和大小,起始地址加上offset就是段地址。
中断
- 每一个中断或异常与一个中断服务例程(ISR)相绑定,其关联关系存储在中断描述符表(IDT)中
- iret:没有改变特权级——弹出CS、EFLAGS和SS/EIP;ret:弹出EIP;retf:弹出CS和EIP
物理内存管理
- mmu进行逻辑地址和物理地址的转换,alu存放需要逻辑地址的内存内容
- 物理内存分配的三种方式:最先匹配,最佳匹配,最差匹配
- 最佳匹配容易产生外部碎片(但是比最先匹配好),释放分区比较慢,容易产生无用小碎片
- 最差匹配释放比较慢,容易产生外部碎片,容易破坏空闲分区;优点是避免出现小碎片,中等大小的分配多的时候,效果最好
- 碎片整理的条件:所有进程可动态重定位
- 进程的对换(从内存到外存)就是一种碎片整理过程
- 分页方式不会产生外碎片,因为是顺序排列的
- 段式存储:使用段号和段内偏移寻址,在段表中寻找内存基址和长度
- 段式存储管理:主代码段,子模块代码段,共用库代码段,堆栈段,初始化数据段
- 页式存储管理:物理页面的基本单位是页帧,是2的n次方;逻辑页面的基本单位是页面
- 页帧和页面的转换通过页表,MMU和TB进行;物理内存=帧号*常数+偏移;逻辑偏移=物理偏移,逻辑页号一般不等于物理帧号
- 页表将逻辑页号和物理帧号一一对应起来,包括存在位、修改位、引用位,只读位
- 页表访问带来了一次获取页表项的性能开销,页表可能非常大
- 为了解决上述问题,采用缓存或者间接访问的方式
- 快表(TLB)和多级页表,快表是对于页表的一次缓存,位于cpu中;多级页表逻辑地址中放的是x级页表的偏移
- 反置页表和页寄存器都是和物理帧相对应,
- 寄存器内容包括:使用位(此帧是否被进程占用)、占用页号(对应的页号)、保护位
- 内存管理方式主要分为:页式管理、段式管理和段页式管理。
页式管理的基本原理是将各进程的虚拟空间划分为若干个长度相等的页。把内存空间按页的大小划分为片或者页面,然后把页式虚拟地址与内存地址建立一一对应的页表,并用相应的硬件地址转换机构来解决离散地址变换问题。页式管理采用请求调页和预调页技术来实现内外存存储器的统一管理。
优点:没有外碎片,每个内碎片不超过页的大小。
缺点:程序全部装入内存,要求有相应的硬件支持,如地址变换机构缺页中断的产生和选择淘汰页面等都要求有相应的硬件支持。增加了机器成本和系统开销。
段式管理的基本思想是把程序按内容或过程函数关系分成段,每段有自己的名字。一个用户作业或者进程所包含的段对应一个二维线性虚拟空间,也就是一个二维虚拟存储器。段式管理程序以段为单位分配内存,然后通过地址映射机构把段式虚拟地址转换为实际内存物理地址。
优点:可以分别编写和编译,可以针对不同类型的段采取不同的保护,可以按段为单位来进行共享,包括通过动态链接进行代码共享。
缺点:会产生碎片。
段页式管理,系统必须为每个作业或者进程建立一张段表以管理内存分配与释放、缺段处理等。另外由于一个段又被划分为若干个页,每个段必须建立一张页表以把段中的虚页变换为内存中的实际页面。显然与页式管理时相同,页表也要有相应的实现缺页中断处理和页面保护等功能的表项。
段页式管理是段式管理和页式管理相结合而成,具有两者的优点。
由于管理软件的增加,复杂性和开销也增加。另外需要的硬件以及占用的内存也有所增加,使得执行速度下降。
特权级和切换
- RPL数据段特权级、DPL目标特权级、CPL当前代码段特权级
- 中断、陷入门的比较:
CPL<=DPL[门](代码段能够通过门)&CPL>=DPL[段](通过后访问的段级别更高)
MAX(CPL,RPL)<=DPL - 段寄存器低两位:CPL
- IDT中断描述符表保存了不同特权级跳转之后的地址信息,TSS保存了不同特权级用到的寄存器(堆栈)中的信息
- 建立TSS:对内存做初始化--TSS初始化--GDT中填写描述符--设置TSS Selctor
ucore建立段/页表
- Linear Address包括:目录;页表项;偏移地址
- 页目录的起始地址保存在CR3中
- 页机制完成虚地址映射,段机制完成对等映射
- 内存管理主要由页机制进行,安全管理主要由段机制进行
虚拟存储
- 虚拟存储是非连续内存存储的延续,可以在前者的基础上使用外存
- 覆盖:一个进程,通过没有调用关系的模块之间的并行性,给出模块间的逻辑覆盖结构,发生在运行程序的内部模块之间
- 交换:以进程为单位,不需要模块间的逻辑覆盖结构,发生在内存进程间
- 我们会发现:覆盖有着复杂的调用关系,很难由操作系统来完成;有着模块之间的调用,并且由操作系统调度的,就是虚拟存储
- 分支局部性:一条跳转指令的两次执行,很可能跳到相同的内存位置
- 虚拟管理在原先的页表项中加入了一些标志位:访问位,修改位,保护位,驻留位
- 驻留位:页面是否在内存当中
- 修改位:表示在内存中的该页是否被修改过
- 访问位:表示该页面是否被经常访问过(用于换入换出)
- 保护位:表示访问方式
- 缺页寻址机制:
逻辑地址:10位的地址,10位的逻辑页帧号,12位的页内偏移、
物理地址:20位物理页帧号,12位的偏移
使用一个二级的页表结构。
信号量与管程
- 信号是一种抽象数据类型,有一个整型变量和两个原子操作组成
- P() sem减1,如果sem<0进入等待,否则继续
- V() sem加1,如果sem<=0,唤醒一个等待进程