操作系统学习笔记-2:体系结构设计和运行机制

一. 操作系统的体系结构

1. 传统的操作系统结构

(1)无结构操作系统:

早期的操作系统没有真正意义上的“结构”可言,只是大量的过程的集合,过程之间可以互相调用,导致操作系统内部复杂而混乱。

(2)模块化结构操作系统:

模块化结构的 OS 基于程序模块化开发的思想,按照功能划分了多个具有一定独立性和大小的模块,每个模块有自己的功能,同时互相之间能够通过接口实现交互。模块之下又有子模块,以此类推。

  • 模块的大小:划分过小,就会引起模块之间联系过多;划分过大,就会引起内部联系增加,复杂度提高
  • 模块的独立性:两个衡量标准,即低耦合、高内聚。耦合度指的是模块之间的互相联系和影响,内聚性指的是模块内部各部分之间的紧密程度

模块化开发的 OS 虽然提高了 OS 设计的正确性、可理解性、可维护性,加速了开发过程,但是也存在着一定的问题:接口难以满足实际需求;多个决定齐头并进,呈现出“无序性”。

(3)分层式结构操作系统

为了将“无序性”转化成“有序性”,采用了自底向上方法,在目标系统和裸机(宿主)系统之间铺设多个中间层,使得目标系统最终得以在裸机系统上运行。

从层次来看,为了使每一步设计都建立在可靠的基础上(这正是模块化结构 OS 缺失的),规定每一层仅能使用其底层提供的功能和服务 —— 这就使得调试变得非常容易,比如调试 A2 层的时候,可以只考虑 A1 层,因为 A2 层依赖 A1 层的服务和功能。一层一层自底向上增添,每一层实现一些功能,最后构成一个完整的 OS。

聚焦于单个层次,每个层次都由若干个模块构成。

分层式结构的 OS 虽然保证了系统的正确性、可扩充性和易维护性,但是由于是分层单向依赖,使得层次和层次之间的通信成为了一个问题。执行一个简单的功能,可能需要穿越多个层次完成通信。

2. 微内核操作系统结构

2.1 特点

(1)足够小的内核:

包含 —— 与硬件处理紧密相关的部分;基本的功能;客户与服务器之间的通信

(2)基于客户/服务器模式 :

OS 最基本的部分放在内核中,其它绝大部分功能则在微内核外面的一组服务器(进程)中实现,比如 IO 设备管理服务器、进程服务器等。客户与服务器之间通过消息传递机制实现信息交互,如下图:

(3)应用“机制与策略分离”原理

  • 机制:实现某个功能的具体执行机构
  • 策略:在机制基础上借助某些算法实现功能

在微内核 OS 中,通常将机制放在 OS 的微内核中。

(4)采用面向对象技术:

基于“抽象”“隐蔽”原则控制系统的复杂性,基于“对象”“封装”“继承”确保系统的正确性、可靠性、易修改性、易扩展性。

2.2 功能

  • 进程(线程)管理:进程通信、切换、调度等
  • 低级存储器管理
  • 中断和陷入管理

2.2 优缺点

优点 缺点
提高了系统可扩展性 采用了小的内核
增强了系统的可靠性 C/S模式和消息传递机制
较好的可移植性 运行效率有所降低
提供了对分布式系统的支持 传统 OS 只需进行两次变态,而微内核 OS 需进行多次变态(具体下文会提及)
融入了面向对象技术

二. 操作系统的运行机制

1. 相关概念普及

1.1 两种指令

特权指令:

指的是有特殊权限的指令,比如:清内存、置时钟、分配系统资源、修改虚存的段表和页表,修改用户的访问权限等。这类指令使用不慎将导致系统崩溃,因此不能直接向用户程序开放使用这些指令的权限。

非特权指令:

相对于特权指令来说的普通指令,任何程序都可以使用,比如运算指令等。

1.2 两种处理器状态

CPU 的核心态或者用户态可以看作一种状态,一种模式或者一种级别。

**核心态(目态):**当处于核心态时,可以使用特权指令或者非特权指令(陷入指令是例外,它只能在用户态下执行)

**用户态(管态):**当处于用户态时,只能使用非特权指令

1.3 两种程序

**内核程序:**运行在核心态下,可以执行特权指令

**应用程序:**运行在用户态下,为了系统安全着想,它只能执行非特权指令

2. 操作系统的内核

先看计算机系统的结构层次:

操作系统学习笔记-2:体系结构设计和运行机制_第1张图片

重点在 OS 的内核,它是 OS 最基本、最核心的部分。

大内核:

操作系统学习笔记-2:体系结构设计和运行机制_第2张图片

如果内核不仅包括了时钟管理、中断处理以及原语(设备驱动、CPU 切换),还包含了进程管理、存储器管理以及设备管理等功能,那么就属于大内核

大内核虽然使得内部代码非常庞大复杂,但是在用户态与核心态之间的切换,相对来说是很快的,这是因为大内核集成了进程管理、存储器管理等;

微内核:

如果内核仅由时钟管理、中断处理以及原语(设备驱动、CPU 切换)构成,那么这种内核属于微内核

微内核的代码结构相对来说就很清晰、便于维护,但是由于微内核只集成了时钟管理、中断处理等这些最最基本的功能,所以在涉及到进程管理、存储器管理等时,就可能需要频繁变态(切换到用户态),而变态是需要消耗时间的,这无疑就会降低运行的性能。

3. 中断机制

3.1 为什么需要中断?

在第一篇笔记中,我们说过,早期的操作系统只能串行跑程序,一个完成之后才能轮到下一个,这种情况下资源利用率显然是很低的;于是后来有了多道批处理系统,可以并发执行程序,为什么能够并发执行呢?这其实依赖于中断机制。

  • CPU 从用户态切换到核心态,能且只能通过 中断 这一途径
  • 而从核心态切换到用户态,只需要执行一个特权指令

3.2 中断的分类

  • 内中断(异常、例外、陷入):内中断的中断信号来自于 CPU 内部,和执行的指令有关

    • 自愿中断:比如 系统调用 这一指令中断
    • 强迫中断:硬件故障、软件中断(比如不合法的运算)
  • 外中断(狭义的中断):外中断的中断信号来自于 CPU 外部,和执行的指令无关

    • 外设请求:比如 I/O 操作完成后发出的中断信号
    • 人工干预:比如用户强行终止进程

此外,还有另一种分类方式:

  • 硬中断:是由诸如磁盘,网卡,键盘,时钟等的外设发出中断信号的
  • 软中断:是执行中断指令产生的,通常是一些对 I/O 的请求

3.3 中断的过程演示

我们用一个过程来演示中断的发生:

(Session 1)时间片用完了:

比方说,现在有个 A 进程正在用户态下运行。一段时间后,该进程消耗完了本次的时间片,那么操作系统内核中的计时部件知道时间到了,就会向 CPU 发射一个中断信号。CPU 接收到中断信号后,肯定要针对本次中断进行处理,但是它自己是无法处理的,需要借助操作系统内核的中断处理程序处理,而该程序又需要运行在核心态下,所以,此时 CPU 由一开始的用户态切换成了核心态。操作系统内核的中断处理程序针对中断信号进行处理,发现原来是 A 进程的时间片用完了,应该轮到 B 进程运行了,那么它就会把 CPU 使用权移交给 B 进程,让 B 进程开始运行,此时 CPU 也切换回用户态。

(Session 2)要进行输出:

B 进程正常运行,这时候执行到的某一行代码要求进行输出操作。前面我们说过,输入输出是特权指令,B 作为一个普通的用户程序来说,是不能直接执行特权指令的,因此,B 进程通过系统调用的方式向 CPU 发射一个中断信号,CPU 接收到中断信号后,肯定要针对本次中断进行处理,但是它自己是无法处理的,需要借助操作系统内核的中断处理程序处理,而该程序又需要运行在核心态下,所以,此时 CPU 由一开始的用户态切换成了核心态。操作系统内核的中断处理程序针对中断信号进行处理,发现原来是 B 进程要进行输出,那么它就会让打印机这一 I/O 设备开始工作。对于 B 进程,此时它要暂停运行,等待 I/O 完成。而这段空闲的时间不能浪费,所以操作系统就会把 CPU 使用权移交给 C 进程,让 C 进程开始运行,此时 CPU 也切换回用户态。

(Session 3)输出完成了:

现在,C 进程和 I/O 设备并发运行,在 I/O 设备搞定了自己的工作后,它会向 CPU 发射一个中断信号。一如既往地,CPU 再次变成核心态,操作系统介入,发现原来是输出工作完成了,应该让上次暂停的 B 进程继续运行了,那么它就会把 CPU 使用权再次移交给 B 进程,让 B 进程往后运行,此时 CPU 也切换回用户态。

4. 系统调用

4.1 为什么需要系统调用

操作系统作为连接 用户/应用程序 和 计算机硬件 的中间层,需要向上提供一些接口以方便用户或者应用程序使用它的服务,这些接口包括命令接口和程序接口。

命令接口即联机命令接口和脱机命令接口,用户可以直接使用这些接口;而程序接口则是由一组系统调用组成的,用户需要通过程序间接使用:

应用程序通过系统调用请求操作系统的服务。系统中的各种共享资源归操作系统管理,因此在用户程序中,凡是和资源相关的操作,都必须通过系统调用的方式向操作系统提出服务请求,由操作系统代为完成,从而保证系统的稳定性和安全性,防止用户进行非法操作。

4.2 分类

  • 设备管理:完成设备的 请求/释放/启动 等
  • 文件管理:完成文件的 读写增删 等
  • 进程控制:完成进程的 创建/撤销/阻塞/唤醒 等
  • 进程通信:完成进程之间的 消息传递/信号传递 等
  • 内存管理:完成内存的 分配/回收 等

这些功能都涉及到了特权指令,因此系统调用虽然是在用户态发出的,但是他的处理是需要在核心态下完成的。

PS:部分的库函数是对系统调用的封装

的 分配/回收 等

这些功能都涉及到了特权指令,因此系统调用虽然是在用户态发出的,但是他的处理是需要在核心态下完成的。

PS:部分的库函数是对系统调用的封装

4.3 过程

传递系统调用的参数 ==> 在用户态下执行陷入指令,发生内中断,进入核心态 ==> 在核心态下执行系统调用相应服务程序 ==> 返回用户程序

你可能感兴趣的:(操作系统)