操作系统
\
操作系统
学习蒋炎岩《操作系统》课程的学习笔记
同时参考课程教科书《Operating Systems:Three Easy Pieces》的中文版 -- 《操作系统导论》
计算机的本质是状态机,一部分存储当前状态,一部分用于在每个时钟周期内计算并转移至下一状态
程序也可以看成一个状态机,并且是计算机状态机的一部分,程序在计算机上的运行即为计算机从某一初始状态开始计算下一状态并转移(执行指令)
为了能够多程序共用计算机中的硬件同时运行,产生了用于调度的操作系统
系统内核
内核是应用连接硬件设备的桥梁,应用程序只需关心与内核交互,不用关心硬件的细节
现代操作系统的内核一般会提供 4 个基本能力:
- 任务调度 - 决定使用 CPU 的进程/线程
- 管理内存 - 决定内存的分配和回收
- 硬件通信 - 为进程与硬件设备之间提供通信能力
- 提供系统调用 - 使应用程序通过系统调用运行需要更高权限的服务
Linux
特点:
- Multitask 多任务操作系统
- SMP 对称多处理
- 每个 CPU 地位相等,对资源的使用权限相同
- 多个 CPU 共享同一个内存,每个 CPU 都可以访问完整的内存和硬件资源
- 可执行文件链接格式 ELF
- Linux 操作系统中可执行文件的存储格式
- ELF 把文件分段,每段都有自己的作用
- Monolithic Kernel 宏内核
- 系统内核的所有模块,比如进程调度、内存管理、文件系统、设备驱动等,都运行在内核态
- 动态加载内核模块,例如大部分设备驱动是以可加载模块的形式存在的,与内核其他模块解耦
微内核:内核只保留最基本的能力,比如进程调度、虚拟机内存、中断等,把一些应用放到了用户空间,比如驱动程序、文件系统等
这样服务与服务之间是隔离的,单个服务出现故障或者完全攻击,也不会导致整个操作系统挂掉,提高了操作系统的稳定性和可靠性
混合类型内核:内核里面有一个最小版本的内核,其他模块在这个基础上搭建,实现时跟宏内核类似,把整个内核做成一个完整的程序,大部分服务都在内核中,像是以宏内核的方式包裹着一个微内核
Windows
特点:
- Multitask 多任务操作系统
- SMP 对称多处理
- 可移植执行文件 PE
- 混合型内核
用户态 & 内核态
根据进程访问资源的特点可以把进程在系统上的运行分为两个级别:
- 用户态(User Mode) - 用户态运行的进程可以直接读取用户程序的数据,拥权限较低
- 内核态(Kernel Mode) - 内核态运行的进程几乎可以访问计算机的任何资源包括系统的内存空间、设备、驱动程序等,不受限制,权限非常高
当应用程序需要执行某些需要特殊权限的操作,就需要向操作系统发起系统调用请求,进入内核态
应用程序使用系统调用时产生一个中断,CPU 中断当前在执行的用户程序,跳转到中断处理程序,也即内核程序开始执行,内核处理完后,主动触发中断,把 CPU 执行权限交回给用户程序,回到用户态继续工作
分级原因
部分 CPU 指令如内存分配,IO 处理等非常危险,如果错用将导致整个系统崩溃,因此 CPU 指令分为 特权指令 和 非特权指令,特权指令只允许由操作系统内核态执行
基于安全的考虑,CPU 提供了特权分级机制,把区域分成了四个 Ring,越往里权限越高,越往外权限越低
操作系统根据 CPU 的特权分级机制,把进程的运行空间分为内核空间和用户空间,分别对应着 CPU 特权等级的 Ring 0 和 Ring 3
- 内核空间(Ring 0)具有最高权限,可以直接访问所有硬件资源,比如硬盘、网卡、内存等
- 用户空间(Ring 3)只能访问受限资源,不能直接访问内存等硬件设备,必须通过系统调用进入内核态,才能访问这些特权资源
进程既可以在用户空间运行,又可以在内核空间中运行
- 当 CPU 运行在 Ring 3 等级上时,进程就运行在用户态,只能访问用户空间地址的内存
- 当 CPU 运行在 Ring 0 等级上时,进程就运行在内核态,有对硬件的所有操作权限,可以执行所有 CPU 指令集,访问任意地址的内存
切换方式
用户态到内核态的常见切换方式包括系统调用,中断和异常
- 系统调用(Trap):用户态进程主动要求切换到内核态的一种方式,用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作,系统调用的核心机制是使用了操作系统为用户特别开放的一个中断
- 中断(Interrupt):外围设备完成用户请求的操作后,会向 CPU 发出相应的中断信号,这时 CPU 会暂停执行下一条指令,转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换,比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等
- 异常(Exception):当 CPU 在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程,切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常
对于中断和异常,系统都是通过中断向量表来找到相应的处理程序进行处理
区别在于中断来自处理器外部,不是由任何一条专门的指令造成,而异常是执行当前指令的结果
系统调用
系统调用按功能大致分为四类
- 设备管理:完成设备(输入输出设备和外部存储设备等)的请求或释放,以及设备启动等功能
- 文件管理:完成文件的读、写、创建及删除等功能
- 进程管理:进程的创建、撤销、阻塞、唤醒,进程间的通信等功能
- 内存管理:完成内存的分配、回收以及获取作业占用内存区大小及地址等功能
系统调用步骤
- 用户态的程序发起系统调用,因为系统调用中涉及一些特权指令(只能由操作系统内核态执行的指令),用户态程序权限不足,因此会引发 Trap(一种中断)
- 发生中断后,当前 CPU 执行的程序会中断,跳转到中断处理程序,内核程序开始执行,也就是开始处理系统调用
- 内核处理完成后,主动触发 Trap,再次发生中断,切换回用户态工作
中断
中断是系统用来响应硬件设备请求的一种异步的事件处理机制
操作系统收到硬件的中断请求,会打断正在执行的进程,然后调用内核中的中断处理程序来响应请求
中断避免了 CPU 轮询等待某条件成立,可以提高系统的并发处理能力
中断处理程序应尽可能快的执行完,以减少对正常进程运行调度的影响
硬中断 & 软中断
linux 将中断分为硬中断和软中断两部分,以避免中断处理程序执行过长和中断丢失的问题
中断处理程序在响应中断时,可能会「临时关闭中断」,这意味着,如果当前中断处理程序没有执行完之前,系统中其他的中断请求都无法被响应,也就是中断丢失
- 硬中断 - 由 CPU 硬件实现的中断机制,比如中断、异常、INT 指令都是由 CPU 实现的中断机制
- 中断和异常属于「硬件中断」,是硬件自动触发的,中断由外部设备触发,异常由 CPU 触发
- INT 指令属于「软件中断」,是由软件程序主动触发的
- 软中断 - 由软件实现实现的中断机制,比如 Linux 实现的软中断守护进程
具体实现
- 硬中断 - CPU 在每一个指令周期的最后,都会留一个 CPU 周期去查看是否有中断,如果有,就把中断号取出,去「中断向量表」中寻找中断处理程序,然后跳过去执行中断处理程序
- 软中断 - 有一个单独的守护进程不断轮询一组标志位,如果哪个标志位有值了,那去这个标志位对应的「软中断向量表数组」的相应位置,找到软中断处理函数,然后跳过去执行软中断处理函数
软中断的作用就是承接原本硬中断处理程序比较复杂且耗时的工作,让硬中断的中断处理函数的逻辑尽可能的简单,从而提高系统的中断响应速度
linux 中的软中断包括网络收发、定时、调度、RCU 锁等各种类型


