软考-系统架构师-计算机系统基础(二)

二、操作系统

2.1、操作系统概述

2.1.1、操作系统分层结构图

用户层
应用层
支撑软件层
系统软件层
核心层
使用
管理
支持
计算机硬件 / 裸机
操作系统
语言处理程序
应用程序
人

2.1.2、核心定义

操作系统(OS)是计算机系统中最基本的系统软件。

它是控制 和管理计算机软硬件资源的核心程序。

2.1.3、三大关键接口

1)人机之间的接口 :用户通过OS使用计算机。接口方式包括 命令行 (如Linux Bash)、图形界面 (GUI)和 系统调用(System Call,程序员使用的接口)。

2)应用软件与硬件之间的接口:应用软件不需要直接操作硬件(如直接读写硬盘扇区),而是通过OS提供的API进行操作,实现了硬件无关性。

3)资源的管理者:管理对象包括:CPU(进程)、内存(存储)、外设(设备)、数据(文件)。

2.1.4、五大管理职能

2.1.4.1、进程管理

核心任务:管理处理器(CPU)。

关键考点 :进程的状态转换、PV操作 (同步与互斥)、死锁问题、线程概念。这是计算题最多的地方。

2.1.4.2、存储管理

核心任务:管理主存储器(内存)。

关键考点 :页式存储(逻辑地址转物理地址)、段式存储、页面置换算法(LRU/FIFO)。

2.1.4.3、设备管理

核心任务:管理辅助存储器及输入输出设备。

关键考点 :I/O控制方式(DMA)、Spooling技术(假脱机)、磁盘调度算法(移臂调度)。

2.1.4.4、文件管理

核心任务:管理信息/数据资源。

关键考点 :索引文件结构(直接/一级/二级索引)、位示图(空闲块管理)。

2.1.4.5、作业管理

核心任务:用户提交任务的管理。

关键考点:作业调度算法(先来先服务、短作业优先等),通常与进程调度结合考察。

2.2、特殊的操作系统

2.2.1、分类图谱

特定平台
网络与分布
基本运行机制
操作系统分类
批处理 OS
分时 OS
实时 OS
网络 OS
分布式 OS
微机 OS
嵌入式 OS
多道: 宏观并行/微观串行

提高资源利用率
时间片轮转

交互性/独占性
高可靠性

规定时间内响应
资源共享
透明性

统一管理
Windows/Linux

多任务/多线程
微型化/可定制

HAL与BSP支持

2.2.2、三大基本操作系统类型

2.2.2.1、批处理操作系统

单道批处理:一次一个作业,内存中始终只保持一道作业。

多道批处理 :一次将多个作业调入内存,让它们竞争CPU资源。多道批处理的主要目的是提高CPU和外部设备的利用率 以及增加系统吞吐量,但不具备交互能力(用户一旦提交作业就无法干预)。

多道批处理特点:

1)多道:内存中同时存放多个作业。

2)宏观上并行:多个作业都在运行中。

3)微观上串行:单核CPU在每一瞬间只能执行一个作业。

2.2.2.2、分时操作系统

工作方式 :采用时间片轮转 (Round Robin) 的方式为多个用户服务。

四大特点(必背口诀:多独交及):

1)多路性:同时有多个用户通过终端连接。

2)独立性 :每个用户感觉像是独占系统,互不干扰。

3)交互性:用户可以与系统进行人机对话。

4)及时性:系统能在极短时间内响应用户请求。

2.2.2.3、实时操作系统

分类:实时控制系统(如飞行控制)、实时信息系统(如订票系统)。

核心要求:

1)高可靠性:系统绝对不能崩溃。

2)时限性 :必须在规定时间内响应并处理。

实时系统的交互能力不如分时系统强。

实时系统的设计目标是"在严格的时间限制内完成任务",而分时系统的目标是"公平地分配CPU"。

2.2.3、网络、分布式与特定平台操作系统

2.2.3.1、网络操作系统

核心功能 :方便有效地共享网络资源(硬件、软件、数据)。

典型代表:Unix, Linux, Windows Server。

局限性:用户必须知道资源在哪台机器上(不透明)。

2.2.3.2、分布式操作系统

定义:是网络操作系统的更高级形式。

核心特性:

1)透明性 (Transparency):这是与网络OS最大的区别。用户不知道也不需要知道资源在网络中的具体位置,整个系统看起来像是一台巨大的、统一的计算机。

2)可靠性:某台机器宕机,任务会自动转移到其他机器,不影响整体服务。

3)高性能:并行处理能力。

2.2.3.3、微机操作系统

Windows:单用户多任务(早期),现代版本为多用户多任务。特点是图形界面(GUI)。

Linux :类Unix系统,特点是源代码公开 、多用户 、多任务 、多线程 、多CPU支持。

2.2.3.4、嵌入式操作系统

运行环境:智能芯片(如ARM, MIPS)。

核心特点:

1)微型化:内核小,节省存储。

2)可定制:针对不同的硬件变化进行配置(剪裁)。

3)高可靠性 & 实时性。

4)易移植性 : HAL (硬件抽象层) 和 BSP (板级支持包)。

BSP (Board Support Package):介于硬件和操作系统内核之间的一层,它的作用类似于PC机上的BIOS,主要负责硬件初始化。

EOS 初始化过程通常是:片级初始化 -> 板级初始化 -> 系统级初始化。

2.3、进程

2.3.1、进程结构图

进程的组成
PCB 的核心内容
进程标识符
状态
位置信息
控制信息
队列指针
优先级
现场保护区
进程 Process
程序块
数据块
进程控制块 PCB

2.3.2、进程的定义

1)动态性:进程是程序在"一个数据集合上运行的过程"。

程序(Program)是静态的代码文件,存放在硬盘上;进程(Process)是动态的执行实例,存放在内存中。

2)独立性 :进程是系统进行资源分配 和调度的一个独立单位。

这是传统操作系统的定义。在现代操作系统中,资源分配 的单位是进程,而调度 (CPU执行)的基本单位通常是线程。但在软考的基础题中,如果未提及线程,默认沿用此定义。

2.3.3、进程的组成

2.3.3.1、程序块

描述进程要完成的功能,是进程执行的代码实体。

特点:多个进程可以共享同一个程序块(例如多个用户同时使用同一个文本编辑器)。

2.3.3.2、数据块

存放进程执行过程中所需的变量、工作区和堆栈。

2.3.3.3、进程控制块 (PCB)

地位:明确指出 PCB 是**"进程存在的唯一标志"**。系统通过 PCB 来感知和管理进程。PCB 创建,进程就创建;PCB 撤销,进程就消亡。

包含信息:

1)标识符:唯一标记一个进程(PID)。

2)状态:记录当前是运行、就绪还是阻塞。

3)现场保护区:当进程被切换走(中断)时,CPU 的寄存器内容(断点、上下文)就保存在这里,以便下次回来能接着算。

4)队列指针:用于将处于相同状态(如都在排队)的进程连成链表。

2.3.4、进程与线程结构图

进程: 资源分配单位
线程2: 调度单位
程序计数器
寄存器
栈 Stack
所有线程共享的资源
内存地址空间
代码 Code
数据 Data
文件 Files
线程1: 调度单位
程序计数器
寄存器
栈 Stack

2.3.5、进程与线程的定义演变

1)程序 -> 进程 -> 线程

这是计算机执行模型的进化路线。

引入进程:为了实现多道程序并发执行(解决CPU利用率问题)。

引入线程 :为了减少 进程并发执行时的时空开销(创建、撤销、切换),进一步提高并发粒度。

2)两大基本属性的分离

在引入线程之前,进程既是"资源分配单位"也是"调度执行单位"。

引入线程后,这两个职能分家了:

进程 (Process) :是拥有资源的独立单位。

线程 (Thread) :是独立调度(CPU执行)的基本单位。

2.3.6、线程间的"共享"与"独占"

1)线程私有(独占)资源

为什么需要私有?因为每个线程要独立执行指令,必须记录自己执行到哪了,计算结果暂存在哪。

程序计数器 (PC):记录下一条要执行的指令地址。

寄存器 (Registers):保存当前的中间计算结果。

栈 (Stack):保存函数调用链和局部变量。

2)线程共享资源

因为线程都属于同一个进程,所以它们共享进程的大部分"家产"。

内存地址空间:所有线程看到的内存视图是一样的。

代码 (Code):执行同一套逻辑(或不同函数)。

数据 (Data):全局变量是共享的(这也是多线程需要同步锁的原因)。

文件 (Files):进程打开的文件,所有线程都能读写。

2.3.7、用户级线程 vs 内核级线程

内核空间 Kernel Space
用户空间 User Space
进程/线程表
线程库 Runtime
看似是一个单线程进程
只能在一个核上跑
独立调度
独立调度
进程 A - 使用用户级线程
用户线程1
用户线程2
用户线程3
用户线程表
进程 B - 使用内核级线程
线程1存根
线程2存根
OS 调度器
进程A PCB
内核线程 TCB1
内核线程 TCB2
CPU Core 1
CPU Core 2

2.3.7.1、用户级线程

谁来管理 :由应用程序内部的线程库 (Run-time System)管理。操作系统内核根本不知道这些线程的存在。

内核视角:内核只看到一个单独的进程(图中的进程 A)。

切换快 :线程切换只需要在用户态通过简单的指针调整即可,不需要陷入内核态(Mode Switch),开销极小。

跨平台:线程库可以运行在任何操作系统上,不依赖底层OS。

调度灵活:应用程序可以根据自己的需求写调度算法(比如数据库系统常偏爱这种)。

一堵全堵:如果其中一个用户线程发起系统调用(如读文件)被阻塞,内核会认为整个进程被阻塞,导致该进程内其他本来能运行的线程也全部暂停。

无法利用多核 :因为内核只把它当成一个进程,所以一次只能分配给一个CPU核心。哪怕你有100个用户线程,也只能挤在一个核上跑(多对一模型)。

2.3.7.2、内核级线程

谁来管理 :由操作系统内核直接管理。内核里有专门的线程控制块(TCB)列表。

内核视角:内核明确知道进程B里有2个线程。

真正的并发 :内核可以将进程B的不同线程分配给不同的CPU核心同时执行(一对一模型)。

不连坐:如果线程1阻塞了(比如等IO),线程2可以继续在另一个核上跑,不受影响。

切换慢:线程切换需要从用户态切换到内核态(System Call),开销比较大。

2.3.7.3、三种映射模型
模型 描述 典型代表 架构评价
多对一 (M:1) 多个用户线程映射到1个内核线程 早期的 Java (Green Threads), 传统的 Unix 优点 :切换极快。 缺点:无法利用多核,一堵全堵。
一对一 (1:1) 1个用户线程对应1个内核线程 Windows , Linux (NPTL), 现代 Java (HotSpot) 优点 :真并行。 缺点:创建线程开销大,线程数有限制。
多对多 (M:N) M个用户线程动态映射到N个内核线程 Go 语言 (Goroutines), Erlang 优点 :集大成者 。既有ULT的轻量级切换,又有KLT的多核并发能力。 难点:实现极其复杂。
2.3.7.4、对比
特性 用户级线程 (User-Level Thread) 内核级线程 (Kernel-Level Thread)
管理者 应用程序(线程库) 操作系统内核
可见性 内核不知道它的存在(以为还是一个进程) 内核全权管理
切换开销 极小 (不需要切入内核态) 较大 (需要切入内核态)
并发性 一个线程阻塞,整个进程都会被阻塞 一个线程阻塞,其他线程继续跑
CPU利用 只能利用一个CPU核心 可以利用多核CPU并行执行

2.3.8、进程的三态模型

2.3.8.1、进程三态转换模型

进程调度
时间片到
等待某个事件发生

如请求I/O
等待的事件已发生

如I/O完成
X 不可直接转换
X 不可直接转换
运行态
就绪态
阻塞态/等待态

2.3.8.2、运行态

定义:进程正在 CPU 上执行。

数量限制 :在单处理机(Single CPU)系统中,同一时刻只能有 1 个进程处于运行态。

多核情况:如果是多处理机,则可以有多个进程同时处于运行态。

2.3.8.3、就绪态

定义:万事俱备,只欠东风(CPU)。

资源情况:进程已经获得了除 CPU 以外的所有所需资源(如内存、文件句柄等),只要调度程序把 CPU 分配给它,它就能立刻运行。

排队:通常系统会将这些进程排成一个"就绪队列"。

2.3.8.4、阻塞态

定义:进程正在等待某个事件发生(如等待用户输入、等待磁盘读取完成、等待打印机空闲)。

资源情况:此时即使给它 CPU,它也无法运行,因为它缺的是数据或外设响应,而不是计算能力。

2.3.8.5、运行 →\to→ 就绪

原因 :时间片到。

在分时系统中,为了公平,每个进程每次只能运行一小段时间(时间片)。用完了,OS 就会强行把它暂停,放回就绪队列排队,换别人上。

2.3.8.6、运行 →\to→ 阻塞

原因 :等待某个事件发生(主动请求)。

进程运行过程中,代码执行到了 scanf(读键盘)或 read(读文件)等指令,或者执行了 P操作(申请被锁住的资源)。进程主动放弃 CPU,进入睡眠。

2.3.8.7、阻塞 →\to→ 就绪

原因 :等待的事件发生(被动唤醒)。

硬盘数据读完了、用户按下回车了、或者 V操作 释放了资源。硬件会发中断通知 OS,OS 把该进程从阻塞队列移到就绪队列。注意:醒来后不能直接运行,必须先去就绪队列排队!

2.3.8.8、就绪 →\to→ 运行

原因 :调度。

CPU 空闲了,调度程序(Scheduler)从就绪队列中选中了这个进程,把 CPU 分配给它。

2.3.8.9、不可逆转换

阻塞 ≠\neq= 运行:阻塞结束必须先回就绪态排队,绝对不能直接抢 CPU。

就绪 ≠\neq= 阻塞:就绪进程没有执行代码,不可能发出 I/O 请求,所以不会直接变阻塞。只有正在运行的进程才能发出阻塞请求。

2.3.9、调度算法

2.3.9.1、分类

调度方式
非抢占式
抢占式
具体算法
先来先服务
短作业优先
时间片轮转
高响应比优先
优先级调度
进程调度算法

2.3.9.2、先来先服务

原理:谁先到就服务谁,像超市排队结账。

非抢占式:一旦获得CPU,就一直运行直到结束或阻塞。

缺点:存在**"护航效应" (Convoy Effect)**。如果一个长作业先到,后面一堆短作业都要等很久,导致平均等待时间很长。

适用:作业调度(现在很少单独用于进程调度)。

2.3.9.3、短作业优先

原理:谁运行时间短,谁先上。

优点 :能获得最短的平均等待时间 和平均周转时间(这是数学上证明过的最优解)。

缺点 :"饿死" (Starvation) 现象。如果一直有短作业源源不断地来,长作业可能永远得不到执行。

类型:有"非抢占式SJF"和"抢占式SJF"(也叫最短剩余时间优先 SRTN)。

2.3.9.4、时间片轮转

原理 :每个进程轮流执行一个时间片(如10ms)。用完就去队尾排队。

这是分时操作系统的标配。

公平性:所有进程都能得到响应。

时间片太大 →\to→ 退化为 FCFS。

时间片太小 →\to→ 频繁切换上下文(Context Switch),开销太大,CPU都在忙着切进程,没空干活。

2.3.9.5、高响应比优先

原理:它是 FCFS 和 SJF 的折中方案,既考虑等待时间,也考虑执行时间。

公式(必背计算公式):

响应比Rp=等待时间+要求服务时间要求服务时间=1+等待时间要求服务时间响应比 R_p = \frac{等待时间 + 要求服务时间}{要求服务时间} = 1 + \frac{等待时间}{要求服务时间}响应比Rp=要求服务时间等待时间+要求服务时间=1+要求服务时间等待时间

分析:

作业刚到时,等待时间=0,响应比=1。

随着等待时间增加,响应比越来越高,最终长作业也能获得CPU,避免了"饿死"现象。

2.3.9.6、优先级调度

原理:根据优先级高低来分配CPU。

静态优先级:创建进程时确定,不再改变。

动态优先级:随运行情况变化(例如等待越久,优先级越高)。

问题:低优先级进程可能"饿死"。

2.3.9.7、抢占式 & 非抢占式

非抢占式:除非进程自己放弃(结束或阻塞),否则谁也抢不走它的CPU。

抢占式:

1)如果有更高优先级 的进程到了,或者时间片用完了,系统会强行剥夺当前进程的CPU,分配给新进程。

2)实时系统 和现代分时系统(Windows/Linux)都必须是抢占式的。

2.3.10、进程的标准五态

2.3.10.1、标准五态模型

基础三态
允许/提交
调度
时间片到
等待事件
事件发生
执行结束/异常
新建态
终止态
就绪态
运行态
阻塞态

适用场景:考题问"进程是如何创建的"或"进程结束后资源如何回收"时。

2.3.10.2、新建态

进程正在被创建。系统为其分配了 PCB,但还没有把它放入内存的就绪队列中(可能因为内存满了,或者为了控制系统并发度)。

关键点 :此时进程不在就绪队列中。

2.3.10.3、终止态

进程运行结束或出现错误被系统杀掉。

关键点:系统保留其 PCB 一段时间(为了审计或统计),但进程已经不再执行指令,资源正在被回收。

2.3.11、进程的七态模型

2.3.11.1、七态模型

外存中 (静止/挂起)
内存中 (活动)
内存充足
调度
时间片到
等待事件
事件发生
结束
挂起
挂起
激活
激活
事件发生
内存不足
新建态
终止态
运行态
活动就绪
活动阻塞
静止就绪
静止阻塞

2.3.11.2、基础概念

这是操作系统中最完整的模型。它在"标准五态"的基础上,引入了**挂起(Suspend)**机制。

就绪态 →\to→ 分裂为 活动就绪 (内存) 和 静止就绪(磁盘)。

阻塞态 →\to→ 分裂为 活动阻塞 (内存) 和 静止阻塞(磁盘)。

总数计算 :新建 + 终止 + (活动就绪 + 静止就绪) + 运行 + (活动阻塞 + 静止阻塞) = 7态。

2.3.11.3、新建 →\to→ 静止就绪

系统想创建进程,但发现内存极其紧张,干脆直接把新进程创建在磁盘的交换区里,排队等着进内存。

2.3.11.4、静止阻塞 →\to→ 静止就绪

进程在磁盘里被挂起(比如因为等 I/O),此时 I/O 完成了。它不会直接飞回内存(变成活动就绪),而是变为"静止就绪"(依然在磁盘里,但状态变了,只要一进内存就能跑)。

2.3.12、同步与互斥

2.3.12.1、逻辑图

同步 (Synchronization)
定义: 速度有差异, 需要配合
类型: 直接制约关系
形象比喻: 张三李四配合工作
目标: 有序执行, 前仆后继
互斥 (Mutual Exclusion)
定义: 争夺临界资源
类型: 间接制约关系
形象比喻: 千军万马过独木桥
目标: 只能一个一个过
进程间的制约关系
临界资源: 一次只允许一个进程使用的资源
临界区: 访问临界资源的那段代码

2.3.12.2、基础概念

1)临界资源

定义 :系统中一次只允许一个进程访问的资源。

例子:物理设备(如打印机、磁带机)、共享变量(如全局变量 count)。

生活类比:公用电话亭、独木桥。

2)临界区

定义 :进程中访问临界资源的那段代码。

注意 :临界资源是硬件或数据,临界区是代码。我们通过控制代码的执行(加锁),来保护资源。

2.3.12.3、互斥

性质 :间接制约关系。

为什么叫间接? 因为进程 A 和 进程 B 可能根本互不相识,它们只是因为都要抢同一个资源(打印机),才被迫产生了排队关系。

解决原则:空闲让进、忙则等待、有限等待、让权等待。

2.3.12.4、同步

性质 :直接制约关系。

为什么叫直接? 因为进程 A 和 进程 B 是为了完成同一个大任务而配合的,它们之间有直接的消息传递或依赖关系(源于程序逻辑本身)。

假设任务是:张三把东西送到 A 点,李四才能从 A 点把东西运到 B 点。

即使李四骑车很快,他也必须停下来等 张三先走到 A 点。这就是速度有差异,在一定情况停下等待。

同步的核心是顺序。必须先做完甲,才能做乙。

2.3.12.5、经典场景
场景 类型 关键词 判别技巧
打印机 互斥 抢占、独占 资源只有一份,谁抢到谁用
数据库写锁 互斥 写操作 防止数据写乱
生产者-消费者 同步 + 互斥 缓冲区空/满 缓冲区满了生产者必须等消费者取走
流水线作业 同步 前后工序 上一道工序做完,下一道才能开始
公共汽车 同步 司机/售票员 关门后才能开车(同步),到站后才能开门(同步)

2.3.13、信号量和PV操作

2.3.13.1、基础概念

1)原语:这意味着 PV 操作是不可中断的,要么做完,要么不做,执行过程中不允许切换进程。

2)信号量:它是一个特殊的全局变量,用于表示资源的数量。

3)信号量的物理含义(必背):

① S>0S > 0S>0:表示系统中当前可用的资源数量。

② S=0S = 0S=0:表示资源刚好分完,且没有进程在排队。

③ S<0S < 0S<0:表示资源不够用了。SSS 的绝对值 (∣S∣|S|∣S∣)表示正在等待该资源的进程数(即排队人数)。

2.3.13.2、PV操作逻辑流程图

V操作: 释放/解锁资源
Yes (有人在排队)
No (无人排队)
开始
S = S + 1
S <= 0 ?
从等待队列

唤醒一个进程
继续执行
P操作: 申请/锁定资源
Yes (资源不足)
No (资源足够)
开始
S = S - 1
S < 0 ?
自我阻塞

放入等待队列
继续执行

2.3.13.3、P操作

口诀 :"先减后判,负则阻"。

1)S = S - 1:不管有没有,先预订一个。

2)如果减完后 S<0S < 0S<0:说明刚才那是透支的,没资源了,自己乖乖去阻塞(排队)。

3)如果减完后 S≥0S \ge 0S≥0:说明还有存货,拿走资源,继续执行。

2.3.13.4、V操作

口诀 :"先加后判,不大于0则唤"。

1)S = S + 1:我用完了,把资源还回去。

2)如果加完后 S≤0S \le 0S≤0:说明 SSS 之前是负数(比如 -1, -2),意味着还有兄弟在排队等待。所以我归还的这个资源不能闲着,必须立刻唤醒队列里的一个进程。

3)如果加完后 S>0S > 0S>0:说明 SSS 之前是 ≥0\ge 0≥0 的,没人排队,资源放回库房就行。

2.3.13.5、深度思考

为什么 V 操作中判断条件是 S≤0S \le 0S≤0 而不是 S<0S < 0S<0?

1)假设 S=−1S = -1S=−1(表示有 1 个人在排队)。

2)现在我执行 V 操作:S=−1+1=0S = -1 + 1 = 0S=−1+1=0。

3)此时 S=0S=0S=0。虽然现在不欠资源了,但刚才那个 S=−1S=-1S=−1 的状态说明确实有人在等。所以我必须去唤醒那个人。

4)所以,只要 SSS 加完之后还是非正数 (≤0\le 0≤0),就说明刚才肯定是负数,就必须唤醒。

2.3.13.6、例题

有 2台 打印机,3个 进程要互斥使用打印机。 问:信号量 SSS 的初值是多少?取值范围是多少?

1)确定初值:信号量初值 = 资源的初始数量。

因为有 2 台打印机,所以 Sinitial=2S_{initial} = 2Sinitial=2。

2)阶段 1(资源充足) :进程 A 申请:S=2−1=1S = 2 - 1 = 1S=2−1=1 (拿到)。进程 B 申请:S=1−1=0S = 1 - 1 = 0S=1−1=0 (拿到,此时资源刚好空)。

3)阶段 2(资源耗尽,开始排队) :进程 C 申请:S=0−1=−1S = 0 - 1 = -1S=0−1=−1 (阻塞,此时有 1 个进程在排队)。

4)确定范围:

最大值:2(就是初值,谁都没用的时候)。

最小值 :当所有进程都来申请时。资源总量 - 进程总数 = 2−3=−12 - 3 = -12−3=−1。此时表示:2 个进程在运行(拿到了),1 个进程在排队(S=-1)。

结论 :取值范围是 −1,2-1, 2−1,2。

2.3.14、前趋图

2.3.14.1、前趋图结构

并行执行: 起始进程
信号量 S1
信号量 S2
信号量 S3
信号量 S4
A: 绞肉
B: 切葱末
C: 切姜末
D: 搅拌
E: 包饺子

2.3.14.2、定义与组成

定义 :前趋图是一个有向无环图 (DAG),用于描述进程之间执行的先后顺序。

结点 (Nodes):表示一个进程或一个程序段(如 A、B、C...)。

有向边 (Arrows) :表示前趋关系(Precedence Relation)。如果存在 A→DA \to DA→D,则表示 A 必须在 D 开始之前完成 。这种关系对应的就是 同步 (Synchronization) 关系。

2.3.14.3、关键术语

直接前趋:如 A 是 D 的直接前趋。

直接后继:如 D 是 A 的直接后继。

起始进程 (Initial Process) :没有前趋 (没有箭头指向它)的结点。如A、B、C。它们可以同时并发执行(因为谁也不用等)。

终止进程 (Final Process) :没有后继(没有箭头指出去)的结点。如E。它是最终的任务目标。

2.3.14.4、实例分析

并行性:绞肉(A)、切葱(B)、切姜© 互不干扰,可以三个人同时干(并发)。

同步性 :搅拌(D) 必须等 A、B、C 全部 做完才能开始。缺一样都没法搅拌。

顺序性:包饺子(E) 必须等搅拌(D) 做完。

2.3.15、PV操作与前趋图映射

2.3.15.1、原理

Sa (信号量)
Sb (信号量)
Sc (信号量)
Sd (信号量)
进程 A: 绞肉
进程 B: 切葱末
进程 C: 切姜末
进程 D: 搅拌
进程 E: 包饺子

2.3.15.2、信号量定义的铁律

1)数量原则:图中有几根箭头,就必须定义几个信号量。

2)初值原则 :用于**前趋关系(同步)**的信号量,初值一般为 0。

深度理解:为什么是 0?因为同步是"接力赛"。比赛刚开始时,第一棒还没跑完,接力棒还没交出来,所以第二棒能拿到的接力棒数量是 0,必须等。

2.3.15.3、代码填充法则

1)法则一:有后继 →\to→ V操作

如果一个进程屁股后面有箭头指出去,它做完事后必须执行 V(信号量),通知下家。

2)法则二:有前趋 →\to→ P操作

如果一个进程头顶上有箭头指进来,它干活前必须执行 P(信号量),检查上家做完没。

2.3.15.4、易错点

信号量初值区分:

1)互斥(抢厕所):初值 = 1(有一把钥匙)。

2)同步(前趋图/接力赛):初值 = 0(初始没接力棒)。

2.3.16、死锁

2.3.16.1、死锁处理策略逻辑图

处理策略
产生的四个必要条件
X 很难破坏
√ 可以打破
√ 可以打破
√ 可以打破
打破其中一个条件
银行家算法
死锁 Deadlock
互斥条件

Mutual Exclusion
保持和等待

Hold and Wait
不剥夺

No Preemption
环路等待

Circular Wait
预防死锁

Prevention
避免死锁

Avoidance
通常保留
一次性申请所有资源
申请不到就释放已有的
资源有序分配法

2.3.16.2、死锁的四大条件与预防

1)互斥:资源只能被一个进程使用。

这个条件通常无法破坏(打叉),因为打印机等设备的物理特性决定了它必须互斥使用。

2)保持和等待:占着碗里的(保持),看着锅里的(等待)。

策略 :要求进程一次性申请所有资源,否则一个也不给。

3)不剥夺:别人手里的资源,不能强行抢过来。

策略 :如果申请不到新的,就把手里现有的释放(剥夺自己)。

4)环路等待:A等B,B等C,C等A。

策略 :给资源编号,按顺序申请(有序资源分配法)。

2.3.16.3、最少资源数计算

场景 :有 nnn 个进程,每个进程都需要 kkk 个资源。问系统至少要有几个资源才不可能发生死锁?

极端倒霉情况 :每个进程都拿到了 k−1k-1k−1 个资源(只差 1 个就圆满了),此时系统刚好没资源了 →\to→ 死锁。

破解公式: 系统资源数≥进程数×(每个进程所需资源数−1)+1系统资源数 \ge 进程数 \times (每个进程所需资源数 - 1) + 1系统资源数≥进程数×(每个进程所需资源数−1)+1

例子:

1)3 个进程,都需 5 个资源。

2)阈值 = 3×(5−1)+1=12+1=133 \times (5-1) + 1 = 12 + 1 = 133×(5−1)+1=12+1=13。

3)只要资源数 ≥13\ge 13≥13,就绝对不会死锁。

2.3.17、银行家算法

2.3.17.1、核心思想

在分配资源之前,先算一算,借出去这笔钱后,系统会不会破产(进入不安全状态)。如果会破产,就不借(推迟分配)。

2.3.17.2、三大关键矩阵

1)Max (最大需求):进程总共要多少。

2)Allocation (已分配):进程现在手里有多少。

3)Need (还需) :这是解题的关键,通常不直接给,要自己算! Need=Max−AllocationNeed = Max - AllocationNeed=Max−Allocation

2.3.17.3、解题五步法

1)计算当前剩余资源

公式 :Available=系统总资源−∑(所有进程的已分配资源)Available = 系统总资源 - \sum(所有进程的已分配资源)Available=系统总资源−∑(所有进程的已分配资源)

2)计算需求矩阵

用 Max 减去 Allocation。

算出所有进程的 Need。

3)试探分配

拿着手里的闲钱去比对谁的 Need 能够被满足。

4)运行与回收

运行结束后,它会把它手里所有的资源(Allocation)都还给系统。

注意:不是加 Need,也不是加 Max,是加它占用的资源!

5)循环判断

循环类推,直到所有进程都运行完,就是一个安全序列。

2.3.17.4、样例题

1)题目描述

假设系统中由三类互斥资源 R1、R2、R3,可用资源总量分别是 9、8、5。

在 T0 时刻,系统中有 P1、P2、P3、P4 和 P5 五个进程,这些进程对资源的 最大需求量 (Max) 和 已分配资源数 (Allocation) 如下表所示。

进程 R1 (Max) R2 (Max) R3 (Max) R1 (Alloc) R2 (Alloc) R3 (Alloc)
P1 6 5 2 1 2 1
P2 2 2 1 2 1 1
P3 8 1 1 2 1 0
P4 1 2 1 1 2 0
P5 3 4 4 1 1 3

问题:如果进程按 ______ 序列执行,那么系统状态是安全的?

A : P1→P2→P4→P5→P3P1 \to P2 \to P4 \to P5 \to P3P1→P2→P4→P5→P3

B : P2→P4→P5→P1→P3P2 \to P4 \to P5 \to P1 \to P3P2→P4→P5→P1→P3

C : P2→P1→P4→P5→P3P2 \to P1 \to P4 \to P5 \to P3P2→P1→P4→P5→P3

D : P4→P2→P5→P1→P3P4 \to P2 \to P5 \to P1 \to P3P4→P2→P5→P1→P3

2)解题思路

在做任何判断前,必须先计算两个隐藏数据:

① Need 矩阵 (还缺多少):Need=Max−AllocationNeed = Max - AllocationNeed=Max−Allocation

② Initial Available (系统此时手里还剩多少闲钱):Available=总资源−∑已分配Available = 总资源 - \sum 已分配Available=总资源−∑已分配

准备工作:计算 Need 和 初始可用

R1 已分配总和 :1+2+2+1+1=71+2+2+1+1 = 71+2+2+1+1=7 →\to→ R1 剩 9−7=29-7=29−7=2

R2 已分配总和 :2+1+1+2+1=72+1+1+2+1 = 72+1+1+2+1=7 →\to→ R2 剩 8−7=18-7=18−7=1

R3 已分配总和 :1+1+0+0+3=51+1+0+0+3 = 51+1+0+0+3=5 →\to→ R3 剩 5−5=05-5=05−5=0

初始 Available = (2, 1, 0)

计算流程
P2满足(0,1,0 <= 2,1,0)
P4不满足(0,0,1 > 2,1,0)
P4满足
P1不满足(5>4)
P5运行
初始可用资源 Available: 2, 1, 0
寻找 Need <= 2,1,0
P2

Need: 0,1,0

Alloc: 2,1,1
P4

Need: 0,0,1

Alloc: 1,2,0
P1

Need: 5,3,1
P4暂不可运行

缺R3资源
观察选项:

A以P1开头(Need 5,3,1) -> 排除

D以P4开头(Need 0,0,1) -> 排除

锁定 B 或 C
回收 P2 资源: +2, 1, 1
当前可用: 4, 2, 1
寻找 Need <= 4,2,1
P4

Need: 0,0,1
P1

Need: 5,3,1
P1暂不可运行
观察剩余选项:

B是 P2->P4... (符合)

C是 P2->P1... (P1此时跑不了)

所以选 B
回收 P4 资源: +1, 2, 0
当前可用: 5, 4, 1
验证 B 序列后续: P5->P1->P3
P5

Need: 2,3,1 <= 5,4,1
回收 P5: +1, 1, 3
当前可用: 6, 5, 4
P1

Need: 5,3,1 <= 6,5,4
回收 P1: +1, 2, 1
当前可用: 7, 7, 5
P3

Need: 6,0,1 <= 7,7,5
安全序列 B 验证通过

2.4、存储

2.4.1、页式存储

2.4.1.1、核心概念

基本思想 :为了不浪费内存空间,我们把用户的程序(逻辑空间)和内存(物理空间)都切成一样大小的块。

在程序里,这个块叫 "页" (Page)。

在内存里,这个块叫 "页帧" (Page Frame) 或 "块"。

页表 (Page Table) :这是核心。它是一张映射表,记录了"程序里的第几页"放在了"内存里的第几号房间"。

2.4.1.2、地址转换

逻辑地址结构 :页号 + 页内地址(偏移量)

物理地址结构 :页帧号 + 页内地址(偏移量)

1)切分:根据页面大小,把逻辑地址切开。

比如页面大小 4KB。

4K=2124K = 2^{12}4K=212,说明地址的后 12 位(二进制)是页内地址。前2位是页号。

2)查表:页表映射中根据页号查询页帧号。

3)拼接:页帧号直接拼接偏移量。

口诀 :"页号查表变块号,页内偏移直接抄。"

2.4.1.3、状态位与淘汰

为了管理内存,页表里增加了很多"标记位":

1)状态位 :1=在内存里(可以直接用);0=不在内存里(需要发生缺页中断,去磁盘捞)。

2)访问位 :1=最近被读过;0=最近没人理它(淘汰时优先踢它)。

3)修改位 :1=被改过(脏了);0=没改过(干净的)。

2.4.1.4、为什么要"页式存储"?

主要是解决"碎片"问题。

如果不分页(连续分配) :程序 A 需要 10 平米,程序 B 需要 5 平米。如果内存中间空出了 3 平米、2 平米、4 平米的缝隙,虽然总和有 9 平米,但因为不连续,B 程序根本放不进去。这就叫"碎片"。

页式存储:把程序 B 打碎成 5 个 1 平米的小块。这里塞一块,那里塞一块。只要总空闲面积够,就能塞进去。

代价:因为打碎了,所以需要一个**"账本"(页表)**来记录每一块碎片到底藏在哪了。

2.4.1.5、为什么要"淘汰"?

主要是解决"穷"的问题。

现状:内存(RAM)很贵且小(比如 16G),磁盘(Disk)很便宜且大(比如 1TB)。

需求:我想玩《黑神话:悟空》,这个游戏可能高达 100G,而内存只有 16G。怎么跑?

办法(虚拟存储) :骗 CPU 说我们有很大内存。实际上,只把游戏当前正在玩的那一小部分画面(比如 2G)加载到内存里(状态位=1)。剩下的 98G 都在磁盘上睡大觉(状态位=0)。

2.4.1.6、淘汰的原则是什么?

当内存满了,新的数据要进来,必须踢走一个旧的。

核心逻辑:踢掉那个"最没用 "且"最省事"的页面。

1)第一轮筛选(看访问位)

访问位=0(最近没人理它):优先踢走。

访问位=1(最近刚有人用过):说明可能马上又要用,别踢,留着(也就是 LRU 算法的思想)。

2)第二轮筛选(看修改位)

如果两个页面最近都没人理(访问位都是0),那踢谁?

修改位=0(干净的) :直接覆盖。因为它和磁盘里的备份是一模一样的,踢它不需要写回磁盘,速度快。

修改位=1(脏的/修改过的) :踢它之前,必须把它写回磁盘保存修改,否则数据就丢了。这会消耗 I/O 时间。

结论:优先踢"干净"的,因为省事。

2.4.2、段式存储

2.4.2.1、段式存储核心逻辑图

物理地址计算
越界检查 (核心考点)
逻辑地址 (S, d)
查段表
查段表
No (d >= 段长)
Yes (d < 段长)
段号 S
段内偏移量 d
d < 段长 ?
❌ 越界中断/非法地址
✅ 合法
取出基址 Base
Base + d
物理地址

2.4.2.2、为什么要"段式"?

是为了用户/程序员着想。按逻辑分块,比如主程序段、子程序段、数据段、栈段。

特点 :段的长度是不一样的(Variable Length)。

对比页式是为了物理内存 着想。切成一样大的 4K 小块,塞进内存的缝隙里,没有逻辑意义。缺点是代码可能被从中间切断。

2.4.2.3、段表结构

因为段长不一样,所以段表比页表多了一列数据:

1)页表 :只需要记录 块号(因为大家都知道页长是 4K)。

2)段表 :必须记录 段长 (Limit) 和 基址 (Base)。

基址:这个段从内存哪里开始。

段长:这个段有多大(用于防越界)。

2.4.2.4、地址转换与计算

1)查表 :根据段号,找到对应的 段长 和 基址。

2)安检(越界检查) :规则是段内偏移量 必须小于 段长。

3)计算 :物理地址 = 基址 + 偏移量。

2.4.2.5、优点

多道程序共享内存:比如大家都可以共享同一个"标准函数库"段,只需要在段表里指过去就行。

保护:各段程序修改互不影响。

2.4.2.6、缺点

内存利用率低,内存碎片浪费大。

解释:因为段长不一样(有的 10K,有的 100K),内存里容易出现很多这种"大小不一的空洞"(外部碎片),很难塞进新的段。

2.4.3、段页式存储

2.4.3.1、核心逻辑图

段页式存储最大的考点在于**"三次访存"**(查段表 -> 查页表 -> 访问数据)。
物理地址生成
地址转换流程
逻辑地址
段号 S
页号 P
页内偏移 d
查段表与越界检查
段表 Segment Table
获取该段的页表始址
页表 Page Table
查页表获取块号 f
拼接物理地址 (f+d)
访问物理内存数据
物理内存

2.4.3.2、结构拆解

逻辑地址 = 段号(S) + 页号§ + 页内地址(d)

段号 (15-14) :占 2 位。22=42^2 = 422=4,说明系统最多支持 4个段。

页号 (13-9) :占 5 位。25=322^5 = 3225=32,说明每个段最多只有 32个页。

页内地址 (8-0) :占 9 位。29=5122^9 = 51229=512,说明页面大小是 512B。

2.4.3.3、工作原理

先分段 :把程序按照逻辑(主程序、子程序、数据栈)分成若干个段。

再分页 :把每个段,再切成固定大小的页。

进内存:内存里还是只有固定大小的"物理块",把页塞进去。

2.4.3.4、查表机制

1)段表存什么?

段表里不再存基址了(那是段式干的事)。

段页式的段表里,存的是 "页表的大小" 和 "页表的存放地址"。

2)页表存什么?

页表里存的是 物理块号(和页式一样)。

2.4.3.5、优缺点对比
特性 说明 评价
优点 空间浪费小(因为分页了)、存储共享容易(因为分段了)、能动态连接 集众家之长
缺点 硬件要求高、系统开销大、执行速度大大下降 死穴:慢!
2.4.3.6、为什么速度慢?

页式/段式:查1次表 + 访1次存 = 2次内存访问。

段页式:查段表 + 查页表 + 访存 = 3次内存访问。

2.4.3.7、越界检查有几次?

第一次:检查段号是否超过段表长度。

第二次:检查页号是否超过该段的页表长度。

2.4.3.8、一个程序有几张表?

1 张段表。

n 张页表(每个段对应一张页表)。

2.5、磁盘管理

2.5.1、磁盘物理结构

2.5.1.1、盘面 (Platter)

磁盘是由多个圆形盘片叠在一起组成的。

每个盘片有两个面(上面和下面),都可以存数据。

2.5.1.2、磁道 (Track)

盘面上那一圈一圈的同心圆。

最外圈通常是 0 磁道。

2.5.1.3、扇区 (Sector)

每个磁道被切分成若干个小块,像披萨的一角,叫扇区。

这是磁盘读写的最小单位(通常是 512B 或 4KB)。

2.5.1.4、磁头 (Head)

所有盘面的磁头都连在同一根主杆 (Actuator/Main Rod) 上。

所有磁头是共进退的。要往里移,大家一起往里移。这就引出了**"柱面"**的概念。

2.5.2、存取时间计算

2.5.2.1、基本公式

存取时间=寻道时间+旋转延迟+传输时间存取时间 = 寻道时间 + 旋转延迟 + 传输时间存取时间=寻道时间+旋转延迟+传输时间

2.5.2.2、寻道时间

动作 :机械手臂把磁头移动到指定的磁道(同心圆)上。

比喻:你去图书馆找书,先要走到对应的"书架"前。

考点:这是我们要通过算法(如电梯算法)去优化的重点。

2.5.2.3、旋转延迟

动作 :磁头到了磁道不动,等盘片旋转,把目标扇区转到磁头屁股底下。

比喻:站在回转寿司台前,等你想吃的那盘菜转到面前。

计算公式:通常取旋转一周时间的一半(平均等待时间)。

例如转速 6000r/min →\to→ 100转/秒 →\to→ 转一圈 10ms →\to→ 平均等待 5ms。

2.5.2.4、传输时间

动作:磁头读取数据传给内存的时间。

比喻:把寿司盘子拿下来的时间。

这个时间通常很短,计算题里有时会忽略,或者直接给数值。

2.5.3、核心性质

磁盘属于直接存取存储器 (DASD)。

它可以随机跳到任意位置读写(通过移动磁头),不需要像磁带那样从头卷到尾(顺序存取)。

2.5.4、移臂调度算法

2.5.4.1、算法全家桶
算法名称 英文缩写 核心逻辑 关键词
先来先服务 FCFS 谁先点单先送谁 简单、公平、效率低
最短寻道时间优先 SSTF 谁离我近先送谁 贪心、效率高、可能"饿死"远处的
扫描算法 (电梯算法) SCAN 一条路走到头,再回头 双向、类似电梯
循环扫描算法 C-SCAN 只往一个方向走,到头直接飞回起点 单向、减少边缘等待
2.5.4.2、先来先服务

完全按照请求进来的顺序跑,不管远近。

当前磁头位置:100号磁道。

请求队列:55, 58, 39, 18, 90, 160, 150, 38, 184。

路线 :100 →\to→ 55 →\to→ 58 →\to→ 39 →\to→ 18 →\to→ 90 →\to→ 160 →\to→ 150 →\to→ 38 →\to→ 184。

总移动距离 = ∣100−55∣+∣55−58∣+∣58−39∣...=498|100-55| + |55-58| + |58-39| ... = 498∣100−55∣+∣55−58∣+∣58−39∣...=498。

平均寻道长度 = 55.355.355.3。

评价:虽然公平,但效率极低,基本不会用。

2.5.4.3、最短寻道时间优先

站在当前位置,看谁离我最近,就去谁那儿。

当前磁头位置:100号磁道。

请求队列:55, 58, 39, 18, 90, 160, 150, 38, 184。

谁最近?90 (距离10)。 →\to→ 去 90。

现在在 90。谁最近?(剩55, 58, 150...)。58 (距离32) 最近。 →\to→ 去 58。

现在在 58。55 (距离3) 最近。 →\to→ 去 55。

...以此类推... 39 →\to→ 38 →\to→ 18。

大跳跃 :到了 18 之后,这一带都送完了。最近的只剩那边的大号磁道了,只能跳去 150。

最后 150 →\to→ 160 →\to→ 184。

平均寻道长度 = 27.5。

对比:比 FCFS 快了一倍!

缺点 (饥饿现象):如果磁头一直在 18-50 这一带忙活,突然来个 1000 号的请求,磁头可能永远不过去,因为总有离得更近的插队。

2.5.4.4、扫描算法

就像大楼里的电梯。

如果决定往上走 ,就必须把上面所有层(请求)都送完,直到顶层 (或者最远的请求),才能掉头往下走。

中间不能随意折返(这点和 SSTF 不同)。

应用:解决了 SSTF 的"饥饿"问题,且效率不错。

2.5.4.5、循环扫描

限制磁头只能单向移动(比如只能从里向外)。

当磁头移动到最外层,它不回头服务,而是迅速返回到最内层,重新开始新一轮的"从里向外"。

为什么要这样?:为了让每一个磁道的等待时间更平均(防止两端和中间不均)。

2.5.4.6、流水线公式

总时间=第一条指令完整执行时间+(剩余任务数×流水线周期)总时间 = \text{第一条指令完整执行时间} + (\text{剩余任务数} \times \text{流水线周期})总时间=第一条指令完整执行时间+(剩余任务数×流水线周期)

第一条指令完整执行时间 :就像工厂早上开工,生产第一个零件时,机器要预热,传送带要走完,整个流程必须完整走一遍,没法省时间。(也就是你在上一轮里算出来的"初始启动时间")。

算第一个 :First=T+M+CFirst = T + M + CFirst=T+M+C (雷打不动,先把第一个算出来)。

流水线周期 :从第二个零件开始,因为机器都转起来了,生产每一个新零件只需要增加一个"最慢环节"的时间(这就是瓶颈时间)。

找周期 (Cycle):

  • 单缓冲 :Cycle=max⁡(T+M,C)Cycle = \max(T+M, C)Cycle=max(T+M,C)。
  • 双缓冲 :Cycle=max⁡(T,M+C)Cycle = \max(T, M+C)Cycle=max(T,M+C)。

套公式 :Total=First+(N−1)×CycleTotal = First + (N-1) \times CycleTotal=First+(N−1)×Cycle。

2.6、文件系统

2.6.1、索引文件结构

2.6.1.1、核心结构:混合索引表

磁盘块大小 = 1KB (1024 Bytes)

地址项大小 = 4B

核心常数 N:一个磁盘块能存多少个地址?

N=1024/4=256 个N = 1024 / 4 = \mathbf{256} \text{ 个}N=1024/4=256 个

索引项下标 类型 含义 存取速度
0 ~ 9 直接索引 直接存数据的物理块号 最快 (1次访盘)
10 一级间接索引 存一个索引块的地址 (索引块里存数据块号) 中等 (2次访盘)
11 二级间接索引 存一级索引块的地址 -> 二级索引块 -> 数据 较慢 (3次访盘)
12 三级间接索引 套娃三层 最慢 (4次访盘)
2.6.1.2、直接索引

对应项 :下标 0 ~ 9。

原理:如果不差钱,直接把物理地址写在户口本上。

容量 :10 个地址项,对应 10 个物理块。

逻辑页号范围 :0 ~ 9 页。

特点:访问速度最快,专门给小文件用。

2.6.1.3、一级间接索引

对应项 :下标 10。

原理 :这一项指向一个索引块。这个块里全是物理地址。

容量 :1 个索引块能存 256 个地址。

256×1KB=256KB256 \times 1\text{KB} = 256\text{KB}256×1KB=256KB。

逻辑页号范围 :10 ~ 265 (10 + 256 - 1)。紧接在直接索引之后。

2.6.1.4、二级间接索引

对应项 :下标 11。

原理:套娃。指向一个索引块,这个块里的每一项又指向另一个索引块。

容量 :256×256=65536256 \times 256 = 65536256×256=65536 个物理块。

65536×1KB=64MB65536 \times 1\text{KB} = 64\text{MB}65536×1KB=64MB。

逻辑页号范围 :266 ~ 65801 (266 + 65536 - 1)。紧接在一级索引之后。

2.6.1.5、三级间接索引

对应项 :下标 12。

容量 :256×256×256256 \times 256 \times 256256×256×256 个物理块。

大小 :16M×1KB=16GB16\text{M} \times 1\text{KB} = 16\text{GB}16M×1KB=16GB。

这足以存放非常大的文件了。

2.6.2、访盘次数

假设 i-node 已经被读入内存(通常考试默认这样),读取文件中的数据需要访问几次磁盘?

1)直接索引 :内存查 i-node →\to→ 拿到物理块号 →\to→ 访问数据 。总计:1 次。

2)一级间接 :内存查 i-node →\to→ 读索引块 (1次) →\to→ 拿到物理块号 →\to→ 访问数据 (1次)。总计:2 次。

3)二级间接 :读一级索引块 + 读二级索引块 + 读数据。总计:3 次。

4)三级间接 :读一 + 读二 + 读三 + 读数据。总计:4 次。

2.6.3、位示图

2.6.3.1、核心概念

用途:用来记录磁盘上哪些物理块是用掉的,哪些是空的。

原理 :用 1个二进制位 (bit) 对应 1个物理块。

1:表示占用 (Used)。

0:表示空闲 (Free)。

结构:由若干个**"字" (Word)** 组成,每个字包含若干个**"位" (Bit)**。

2.6.3.2、计算 1:需要多少空间?

题目 :有 NNN 个物理块,字长为 LLL,需要多少个字来存位示图?

公式 :字数=⌈物理块总数字长⌉字数 = \lceil \frac{\text{物理块总数}}{\text{字长}} \rceil字数=⌈字长物理块总数⌉

注意:要向上取整!只要多出1个块,也得占1个完整的字

例题:

物理块数:1000 个

字长:16 位

计算:1000/16=62.51000 / 16 = 62.51000/16=62.5

结果:需要 63 个字(62个填满,第63个字填一部分)。

2.6.3.3、计算 2:位置映射 (在哪儿?)

题目 :物理块号为 NNN,它在位示图的第几个字?第几位? 关键前提 :必须看清题目是从 0 开始编号,还是从 1 开始编号!

从 0 开始编号

物理块号:0,1,2,...0, 1, 2, \dots0,1,2,...

字号、位号:0,1,2,...0, 1, 2, \dots0,1,2,...

公式:

字号=N÷字长(取商)\text{字号} = N \div \text{字长} \quad (\text{取商})字号=N÷字长(取商)

位号=N%字长(取余)\text{位号} = N \% \text{字长} \quad (\text{取余})位号=N%字长(取余)

问题 :64号 物理块在哪?(字长16)

字号:64/16=464 / 16 = \mathbf{4}64/16=4

位号:64%16=064 \% 16 = \mathbf{0}64%16=0

答案 :在 4号字 的 0号位。千万不要因为整除了就觉得在前一个字里!

如果题目说"字号、位号从1开始",公式变为:

  • 字号=(N−1)÷字长+1\text{字号} = (N-1) \div \text{字长} + 1字号=(N−1)÷字长+1
  • 位号=(N−1)%字长+1\text{位号} = (N-1) \% \text{字长} + 1位号=(N−1)%字长+1

三、系统性能

3.1、性能指标

3.1.1、硬件指标

时钟频率 (主频):CPU 的心跳速度,单位 Hz/MHz/GHz。

运算速度:通常用 MIPS (百万条指令/秒) 或 MFLOPS (百万次浮点运算/秒) 衡量。

字长 (Word Length):计算机一次能处理的二进制位数 (32位/64位)。

数据处理速率 (PDR)。

吞吐率:系统在单位时间内处理的任务量。

RASIS 特性:可靠性 (Reliability)、可用性 (Availability)、可维护性 (Serviceability)、完整性 (Integrity)、安全性 (Security)。

3.1.2、网络设备指标

路由器 :设备吞吐量、端口吞吐量、丢包率、时延、时延抖动。

交换机:交换机类型、支持的协议和标准。

3.1.3、软件与系统指标

操作系统:系统可靠性、系统吞吐率、系统响应时间、资源利用率、可移植性。

数据库管理系统 (DBMS):

  • 容量:数据库大小、表数量、记录大小。
  • 性能 :最大并发事务处理能力 、最大连接数、负载均衡能力。

WEB 服务器 :最大并发连接数、响应延迟、吞吐量。

3.2、性能指标计算公式

3.2.1、基础概念

1)时钟周期 (Clock Cycle):CPU 动作的最小时间单位。

时钟周期=1主频时钟周期 = \frac{1}{\text{主频}}时钟周期=主频1

(例如:主频 1GHz,时钟周期 = 1ns)

2)CPI (Clock Per Instruction) :执行一条指令平均需要多少个时钟周期。

  • CPI 越小越好(说明干活快)。

3)IPC (Instruction Per Clock) :每个时钟周期能执行多少条指令。

  • IPC=1/CPIIPC = 1 / CPIIPC=1/CPI。
  • IPC 越大越好。

3.2.2、MIPS 计算 (百万条指令每秒)

MIPS=指令总条数执行时间×106MIPS = \frac{\text{指令总条数}}{\text{执行时间} \times 10^6}MIPS=执行时间×106指令总条数

因为 执行时间=指令数×CPI×时钟周期执行时间 = \text{指令数} \times CPI \times \text{时钟周期}执行时间=指令数×CPI×时钟周期,代入后可得:

MIPS=主频CPIMIPS = \frac{\text{主频}}{CPI}MIPS=CPI主频

或者

MIPS=主频×IPCMIPS = \text{主频} \times IPCMIPS=主频×IPC

3.2.3、MFLOPS 计算 (百万次浮点运算每秒)

MFLOPS=浮点操作次数执行时间×106MFLOPS = \frac{\text{浮点操作次数}}{\text{执行时间} \times 10^6}MFLOPS=执行时间×106浮点操作次数

3.3、系统性能调整

3.3.1、核心定义

什么时候做? 当系统性能降到"最基本水平"时。

做什么? 性能调整的本质就是 查找和消除瓶颈 (Find and Eliminate Bottlenecks)。

3.3.2、调整流程

3.3.2.1、准备工作

识别约束:有什么限制条件?

指定负载:系统要扛多大压力?

设定性能目标:要达到什么指标(如 TPS 多少,响应时间多少)?

3.3.2.2、建立基准

建立边界和期望。

3.3.2.3、实施循环

这是一个持续迭代的过程

收集 (Collect):获取监控数据。

分析 (Analyze):定位瓶颈在哪里。

配置 (Configure):调整参数或代码。

测试 (Test):验证调整有没有效果。

(然后回到收集,周而复始,直到达标)

3.3.4、针对不同对象的调整策略

调整对象 关注重点 (Keywords) 具体措施
数据库系统 资源 & 设计 1. CPU/内存 使用状况 2. 优化数据库设计 (如索引、范式) 3. 优化数据库管理 (如锁机制) 4. 进程/线程 状态 5. 硬盘 剩余空间、日志文件大小
应用系统 体验 & 并发 1. 应用系统的可用性 2. 响应时间 (Response Time) 3. 并发用户数 4. 特定应用的系统资源占用

3.3、阿姆达尔定律

3.3.1、核心概念

定义 :系统中某组件采用更快的执行方式后,整个系统性能的提升程度,取决于该组件被使用的频率(或占总执行时间的比例)。

通俗理解:如果你优化的那部分代码(或硬件)只占整个系统运行时间的 1%,哪怕你把它优化得再快,整个系统的提升也微乎其微。

结论:要想显著提升系统性能,必须优化那些**"占大头"**(执行时间占比高)的部分。

3.3.2、计算公式

R=TpTi=1(1−Fe)+FeSeR = \frac{T_p}{T_i} = \frac{1}{(1 - F_e) + \frac{F_e}{S_e}}R=TiTp=(1−Fe)+SeFe1

RRR (Speedup) :加速比。即改进后的系统比原来快了多少倍。

TpT_pTp :改进前完成整个任务的时间。

TiT_iTi :改进后完成整个任务的时间。

FeF_eFe (Fraction enhanced) :改进比例。

  • 即:被改进的部分在原系统 总执行时间中占的比例。(0≤Fe≤10 \le F_e \le 10≤Fe≤1)

SeS_eSe (Speedup enhanced) :部件加速比。

  • 即:被改进的那部分,其性能提高了多少倍。(Se>1S_e > 1Se>1)

3.3.3、物理意义

改进后的总时间 = 不可改进部分的时间 + 改进部分的新时间

假设原来的总时间是 1:

  1. 不可改进部分 :占 1−Fe1 - F_e1−Fe。这部分时间雷打不动。
  2. 可改进部分 :占 FeF_eFe。现在升级了 SeS_eSe 倍,所以新时间变成 FeSe\frac{F_e}{S_e}SeFe。
  3. 新总时间 :(1−Fe)+FeSe(1 - F_e) + \frac{F_e}{S_e}(1−Fe)+SeFe。

系统总加速比 RRR = 原时间 / 新时间 = 1(1−Fe)+FeSe\frac{1}{(1 - F_e) + \frac{F_e}{S_e}}(1−Fe)+SeFe1

3.4、性能评价方法

3.4.1、经典评价方法

方法名称 英文缩写 核心特点 & 考点
时钟频率法 Clock 最简单 。只看 CPU 频率(主频),忽略了指令系统的差异。频率高 ≠\neq= 速度快。
指令执行速度法 MIPS 用 MIPS (百万指令/秒) 衡量。缺点是没考虑不同指令执行时间不同(如加法快,除法慢)。
等效指令速度法 (吉普森混合法) Gibson mix 加权计算 。通过统计各类指令在程序中出现的比例 (WiW_iWi) 来计算。 ⭐️ 特点:考虑了指令比例不同的问题。
数据处理速率法 PDR PDR=L/RPDR = L/RPDR=L/R。 ⭐️ 特点 :不仅考虑 CPU,还考虑了存储 (CPU + Cache + 主存) 的性能。PDR 值越大越好。
综合理论性能法 CTP 用 MTOPS (每秒百万次理论运算) 表示。先算每个单元的有效计算率,再按字长调整。
基准程序法 Benchmark 目前公认最好 的方法。把应用程序中用得最多、最频繁的核心程序作为标准来测试。

3.4.2、基准测试程序

3.4.2.1、测试精确度排名

如果题目问"哪种测试结果最接近真实性能?",按这个顺序选: 真实的程序 > 核心程序 > 小型基准程序 > 合成基准程序 (越靠左越真实,但也越麻烦;越靠右越简单,但偏差可能越大)

3.4.2.2、常见基准程序对号入座

1)Dhrystone

测 整数 (Integer) 性能。

主要用于测系统编程(编译器、操作系统)能力。

2)Linpack

测 浮点 (Floating point) 性能。

国际上最流行的高性能计算测试(用于测超级计算机)。

3)Whetstone

测 浮点 性能 (Fortran语言编写)。

4)SPEC

测 速度 和 吞吐率。

3.4.2.3、TPC 系列

TPC (Transaction Processing Council) 是专门测数据库 和事务处理 性能的标准。它的单位通常是 tpmC (transactions per minute)。

TPC 类型 测试场景 备注
TPC-A OLTP (联机事务处理) 评价数据库和硬件,旧标准。
TPC-B 纯事务处理 不包括网络,模拟企业计算环境。
TPC-C 联机订货系统 最经典、最常用的在线事务测试标准。
TPC-D/H/R 决策支持系统 测数据仓库、大数据查询分析能力。
TPC-E 大型企业信息服务 模拟复杂的企业环境。
TPC-W Web 应用 (电子商务) 基于互联网的浏览、销售行为测试。

3.5、系统监视

3.5.1、系统监视的三种方式

方式 典型工具/命令 适用场景 备注
1. 系统命令 UNIX/Linux : ps, last, W Windows : netstat 实时查看状态 最快、最直接。 ps: 查看进程 netstat: 查看网络连接端口
2. 系统日志 /var/log (Linux) Event Viewer (Windows) 事后查阅 查看特定时间段内的运行状态,找历史故障原因。
3. 集成监控工具 Perfmon (Windows自带) (以及现在的 Prometheus/Grafana 等) 可视化监控 集成了命令和日志,有图表,适合长期监控趋势。
相关推荐
自传.4 天前
B 站更新|软考架构师案例篇・数据库篇第 1-2 集上线|数据库规范化|索引视图物化视图真题精讲
数据库·软考高级·系统架构师·索引·案例分析·2026软考·软考系统架构师
自传.5 天前
B 站更新|软考架构师案例篇・软件工程篇第 5‑7 集上线|UML 通信图|状态图活动图|构件部署图|OO 三模型真题精讲
系统架构师·部署图·状态图·通信图·活动图·构件图·协作图
xy34535 天前
2026软考软件评测师题目记忆版
软考·软件评测师
Gyr07 天前
浅刷了一遍51CTO软考题库客观题及其解析(4)
学习·软考·知识点·信息安全工程师
夜听莺儿鸣7 天前
901-011_系统分析师基础知识-系统规划与分析
软考·系统分析·系统分析师·系统规划
Gyr07 天前
浅刷了一遍51CTO软考题库客观题及其解析(5)
学习·软考·知识点·信息安全工程师
空空潍7 天前
2026年软考中级软件设计师(二):数据结构
数据结构·软考·软件设计师·软设
妈妈炒的菜8 天前
软考-系统架构设计师
系统架构·软考·系统架构设计师·高级软考
Gyr08 天前
浅刷了一遍51CTO软考题库客观题及其解析(3)
软考·知识点·信息安全工程师·学校
自传.8 天前
B 站更新|软考架构师案例篇・软件工程篇第 1 集上线|数据流图 DFD 精讲|历年真题拆解
系统架构·软考高级·系统架构师·数据流图·dfd·案例分析