操作系统-3 | 4 章
操作系统的基本概念
“差不多”精神
操作系统是人造科学,其中蕴含着“差不多”的思想,学习操作系统不可吹毛求疵。
硬件知识
概念上的结构:
- 一条总线,各种硬件挂在这根总线上;而每个硬件都是通过对应的控制器连接到总线与 CPU 通信。
- 流水线是结构:为了提高效率,模仿工业流水线结构,即每一级都在工作,但是每一级的工作内容都不一样,呈时序关系。
- 执行单元:缓存是让执行单元发挥最大利用效率的结构。
- 存储结构:金字塔形,容量在增大,价格在降低;容量在增大,速度在减小。
- 中断:OS 中最重要的机制,是 OS 获取PC 控制权的根本保证。
抽象
- 根本上存在但是现实中不存在。
- 来源于现实,统一于现实,超出现实。
- 操作系统的抽象在于它来源于硬件,但超出了简单将硬件相叠加的功能,为上层应用提供了更大的资源。
- 软件中不同功能块之间也是一种抽象,对其他功能块而言是一个完整的功能,而非细节描述。
内核态与用户态
- 内核态
拥有最多资源,最高特权。管理 CPU、内存、诊断测试、部分文件系统。 - 用户态
拥有有限的资源,有限的权限。应用程序的管理。 - 状态的识别
CPU 的状态字的设定,在一个程序运行时,此时 CPU 设定的什么状态这个程序就工作在什么态。 - 实现
这种两个状态相分离的实现,是通过“地址翻译”来实现,对用户态下的程序的每一条指令都会检查;而内核态下的程序可以绕过这个翻译。 这是否就为病毒提供可获取最高特权的可能?
操作系统的结构演变
微内核操作系统结构:
进程、内存、文件
- 进程 - 在运行中的程序
- 内存 - 进程的存放场所
- 文件 - 程序和数据的最终存放点
系统调用
- 操作系统是通过系统调用来为应用程序提高服务的。应用程序通过调用操作系统提供 的API来获得操作系统的服务。
- 编译器对一个程序语句先将库函数扩展为系统调用函数,再继续执行。
- 系统调用的种类
- 进程类
- 文件类
- 设备类
- 内存类
- 信息维护类
- 通信类
- 系统调用的3个阶段
- 参数准备,将参数放入寄存器或者压入栈
- 调用识别,通过查询系统调用表或者系统调用函数的内存地址
- 调用执行,执行这个内存地址的系统调用代码
Shell
- 系统 API 过于复杂,是给专门的编程人员使用。而这个 Shell(壳) 就像是操作系统之上的一层壳,有固定的命令或图形操作方式给用户使用;用户可以通过这个 Shell 中的命令来调用系统服务,(固定的命令保证了用户不能直接使用用户态的核心服务,而是有界限的只用 Shell 提供的这些,保证了系统安全)。
- 一个 Shell 就是一个循环程序,始终在等待用户的输入,当用户输入后程序继续执行并 fork 一个子进程来完成用户的命令任务,父进程等待子进程结束。
进程
进程是什么
进程 是正在运行中的程序,是对程序的抽象。也就是说,进程根本上是存在的,是人为定义的,但是物理意义上是不存在的,是抽象出来描述运行中程序的一个概念。
进程模型
进程带来的好处
- 进程的发明让正在运行的程序的具体细节对用户而言是透明的,
- 用户可以同时运行多个程序,并相对串行运行的程序而言可以更快的给出响应,降低了平均响应时间.
- 极大的提高了 CPU 的效率
进程创立/产生/消失
进程创立
进程的创立需要 分配进程控制块
-> 初始化机器寄存器
-> 初始化页表
-> 程序读入内存
-> CPU 设置为 用户态
-> 跳转到程序执行的起始地址
- Unix下
- 第一步:
fork
A进程fork 一个与自己完全一样的进程B, - 第二步:
exec
将 B 进程的地址空间用待要启动的程序内容来覆盖, 跳转到这个新程序的起始地址,开始exec
- 第一步:
- Windows 下
没有fork 这个步骤,直接由系统调用来产生新的进程 - 地址空间
- 地址空间是进程执行的内存空间, 是进程执行的舞台,包含进程执行要用到的所有资源
- 地址空间只是提供资源,真正使用这些资源的叫做
线程
,舞台上的演员. - 进程就是这场舞台剧
进程的产生
进程可以看做有多种类型, 系统进程/用户进程.
- 系统初始化 -> 人类的诞生
- 系统进程创建新的子程序,可以看做是操作系统自然产生的 -> 人类自然繁衍的孩子
- 用户请求创建的新进程可以看做是用户人为创造的 -> 就像试管婴儿.
- 然后子进程可能又会不断的产生新的进程.
进程的消失
进程的终止可以有下面几个原因:
- 寿终: 进程完成任务后自然的退出结束.
- 自杀: 进程自身发生错误, 退出结束.
- 他杀: 被其他进程强行杀死
- 处决: 进程产生异常, 被系统强制终结
进程的层次与状态
进程的层次
进程的层次:用户层/内核层
一个进程在执行过程中可以通过系统调用来产生新的进程, 新的进程叫做 子进程, 原来的进程就是它的 父进程. 在 Unix 系统中有父进程和子进程的概念.
在 WIndows 系统中不存在这种概念,认为所有的进程地位是平等的.
进程的状态
执行
– 就绪
– 阻塞
- 执行 -> 就绪
CPU 在执行
A 进程的过程中, 考虑资源平均的因素, 自然切换到了B进程. 此时 A 进程进入到就绪
状态,等待 CPU 的再一次执行. - 执行 -> 阻塞
CPU 在执行
A 进程的过程中, 遇到需要 I/O 操作,此时 CPU 切换到其他进程, A 进程进入阻塞
状态 - 就绪 -> 执行
A 进程一直在等待 CPU 在选择它来执行,一旦 CPU 选择了 A 程序, A 程序由就绪
进入执行
- 阻塞 -> 就绪
A 进程在处理完 I/O 后,解除阻塞状态,等待 CPU 选择执行,此时正是处于就绪
状态
特别的 :
不存在 阻塞-> 执行 这个过程
因为阻塞到执行中间必须经过就绪
状态, 这是实际上可以操作的,但是阻塞在未进入就绪状态时由被 CPU 选择执行还是阻塞状态,这是没有意义的.不存在 就绪 - > 阻塞
因为一个处于阻塞状态下的进程, 等待它的下一步操作必然是 CPU 来执行它,只有再执行后才会遇到 I/O 操作,进入到阻塞
状态. 这是逻辑上行不通的.一个进程的生命周期
进程管理
维护进程记录
使用进程表
,其中包括每个进程使用的寄存器,程序计数器,状态字,栈指针,优先级,进程的 ID,创建时间,使用 CPU 时间
,等信息. 有些进程处于用户态,但进程表都在内核态.进程控制块,每个进程都有一个进程控制块,可以看做各个进程控制块构成了进程表。
进程在同一个时间只能干一件事情, 公平与效率,如何设置优先级都是总要的.
线程的引入将会解决 同一时间只能做一件事的问题 和 整个进程都会被阻塞的问题(意味着进程中不宜懒于I/O 的部分也不能被执行推进,让整个进程的每一部分都停滞)