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

二、操作系统

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 等) 可视化监控 集成了命令和日志,有图表,适合长期监控趋势。
相关推荐
BOB-wangbaohai2 天前
软考-系统架构师-计算机系统基础(一)
软考·系统架构师·计算机理论基础
大罗辑7 天前
2026软考备考刷题:软件设计师经典100题(5)含详细解析
算法·软考·软件设计师·2026软考·软设备考
qianshanxue118 天前
0-1论软件开发过程 RUP 及其应用-先启阶段、精化阶段、构建阶段和移交(产品化)阶段
系统架构·软考·rup
qianshanxue118 天前
0-2论软件开发过程-或敏捷开发及其应用、2018(Scrum 敏捷开发=规划-站会-迭代-持续集成-客户参与-快速反馈)
软考·敏捷开发·软考论文
夜听莺儿鸣9 天前
902-013_系统架构设计师-综合知识-标准化&知识产权&应用数学
软考·系统架构设计师
辣机小司14 天前
【软件设计师】自编思维导图和学习资料分享(中级已过)
java·c++·软考·软件设计师
BOB-wangbaohai14 天前
软考-系统架构师-软件架构实践
软考·系统架构师
_Minato_16 天前
数据结构知识整理——复杂度的计算
数据结构·经验分享·笔记·算法·软考
网络冒险家16 天前
【信息系统项目管理师教程 第4版】第4章 信息系统管理
软考·信息系统项目管理师