第2章 · 趣味学习

操作系统:电脑的"大管家"

"饿了么么"上线一周,中午高峰期服务器直接卡死。老王冲进机房一顿重启:"进程又卡死了!到底是哪个熊程序占着CPU不拉屎!"小明拦住他:"你这么重启治标不治本。进程为啥卡死?啥叫死锁?为啥内存不够用?这些不搞清楚,你重启到天亮也没用。"

大牛哥推门进来:"操作系统就是电脑的大管家——管CPU、管内存、管设备、管文件、管作业。这章的核心是一个观点、两条线索:用'资源管理'的观点看操作系统;一条线索管资源,一条线索控制程序执行。"

🏛️ 2.1 操作系统的类型与结构

操作系统是计算机中最基本的系统软件,既管软硬件资源又控制程序执行,在计算机与用户之间当接口。给用户的接口是命令/菜单/窗口,给应用程序的接口是API

2.1.1 定义

一句话:操作系统是资源管理者+接口提供者。它合理组织工作流程、有效利用资源。

2.1.2 分类

按功能分:批处理(攒一批一起处理,吞吐高但无交互)、分时(时间片轮流,多用户交互)、实时(严格时限内响应)、网络操作系统、分布式操作系统、嵌入式操作系统、微内核操作系统等。

批处理像洗衣店——攒满一缸再开机器,省水省电但你得等;分时像理发店——师傅每个客人剪一刀轮流来,大家都能在理;实时像救护车——一呼叫立刻出动,晚了要命。饿了么么抢单系统就是实时OS的需求,晚一秒单就被别家抢了。

⚙️ 2.2 操作系统基本原理:五大管理

从资源管理角度看,操作系统有五大管理:处理机(进程)管理、存储管理、设备管理、文件管理、作业管理。这就是"两条线索"里的资源管理线索。

🏃 2.2.1 进程管理:CPU的"排队系统"

处理机是核心资源,进程是处理机管理的最基本概念。进程是系统并发执行的体现——多道程序争夺CPU,用进程作为独立运行和分配资源的基本单位。

1. 进程是啥?程序不是进程

顺序程序按先后次序执行;多道程序系统里资源共享、程序并发执行,"程序"这个静态概念不够用了,于是有了进程——动态的、并发的、独立的运行单位。

💡 秒懂技巧:程序是菜谱(静态的,躺那儿不动),进程是正在炒的这锅菜(动态的,占了灶台、食材、厨师)。同一份菜谱可以同时炒好几锅(一个程序对应多个进程),但每锅是独立的进程。

2. 进程三态转换

进程至少有三个状态:

  • 🟢 就绪:除CPU外资源都齐了,就等CPU分给它
  • 🔴 执行(运行):拿到CPU正在跑。单处理机只有一个进程在执行
  • 🟡 阻塞(等待/睡眠):等某事件(如I/O完成、申请资源)暂停了

状态转换规则:

  • 运行→等待:启动了I/O或申请资源得不到
  • 等待→就绪:等的事件来了(必须先进就绪,不能直接跳运行)
  • 运行→就绪:时间片用完,或更高优先级进程抢占了
  • 就绪→运行:被调度选中
两条死规则:阻塞不能直接进运行,就绪不能直接进阻塞。任何进程在任一时刻只处于一种状态。这是考点,别画错转换箭头。

3. 挂起状态

有些系统加挂起状态:进程被换到外存,原因有:①对换(缓解内存紧张);②终端用户请求暂停;③父进程请求;④负荷调节;⑤OS检查记账。挂起分挂起就绪挂起阻塞,被挂起的进程都不能被调度执行,只能显式激活。

4. 互斥与同步:临界资源的红绿灯

互斥是资源竞争关系——一次只许一个进程用的资源叫临界资源(如打印机),访问它的代码段叫临界区同步是进程协作关系——按制约顺序和速度执行。

临界区协调四准则:①空闲让进;②忙则等待;③有限等待;④让权等待(等的时候释放CPU,别死占着)。

信号量是整数,≥0表示可用资源数,<0表示等待进程数。对它只能做P操作(减1,<0则阻塞自己)和V操作(加1,≤0则唤醒一个等待进程),都是原子操作不可中断。

老王
P和V到底咋记?老是搞反。
小明
P(Passeren=通过/申请)是"申请一把锁",信号量减1,不够就等着;V(Vrijgeven=释放)是"交还钥匙",加1,有人等就叫醒一个。临界区代码就是 P(锁) → 干活 → V(锁)。

生产者-消费者经典问题:两个信号量 Bufempty(空位数,初值=缓冲区大小) 和 Buffull(已用数,初值0)。生产者:生产→P(empty)→存→V(full);消费者:P(full)→取→V(empty)→消费。先P再操作,操作完V,顺序不能乱,否则死锁。

💡 秒懂技巧:生产者像外卖骑手往柜台放餐,消费者像取餐顾客。柜台8个位(Bufempty=8),已放0个(Buffull=0)。骑手放一份:空位少1、已放多1;顾客取一份:已放少1、空位多1。骑手要等空位(P empty),顾客要等餐(P full)——互相配合就是同步。

5. 前趋图

前趋图是有向无环图,表示任务先后制约。直接制约是同一操作内多步骤间的关系(同步的进程间制约),间接制约是多个操作间相同步骤的制约(互斥的进程间制约)。如取指A1、分析B1、执行C1是直接制约;A1、A2、A3之间是间接制约。

6. 进程调度与死锁

调度原因:进程执行完、自己阻塞、P操作阻塞、时间片用完、更高优先级进程出现。调度方式分剥夺(优先级高就抢CPU)和非剥夺(不让出CPU谁也夺不走)。

调度算法:

  • 📋 FCFS(先来先服务/FIFO):按队来,简单但短任务被长任务拖累
  • 优先数调度:按优先级排队,分静态优先级和动态优先级
  • 🔄 轮转法(Round Robin):FCFS排队但每人每次不超过一个时间片,超了排队尾

死锁:若干进程互相竞争对方已占资源,无限期等待不能推进。如P1占R1等R2、P2占R2等R1,谁都不松手——死锁。

死锁四个必要条件(缺一不可):①互斥;②保持和等待(占着已有还等新的);③不剥夺(不能强行夺走);④环路等待

解决策略:预防(打破四个条件之一,如静态分配/有序分配)、避免(银行家算法分配前先算会不会死锁)、检测与恢复(发生后处理)。实际上死锁概率小,检测恢复的代价通常比预防避免小。

💡 秒懂技巧:死锁四条件像四人围坐、每人左手拿一根筷子、都等对方放下右手那根——互斥(筷子一次一人用)、保持等待(占着左手等右手)、不剥夺(不能抢)、环路等待(四人成环)。破任何一个就不死锁:规定一次拿两根(破保持等待)、编号按序拿(破环路)。
🎮 实战场景:饿了么么订单系统和库存系统互相等对方释放数据库连接——订单系统占着订单连接等库存连接,库存系统占着库存连接等订单连接。这就是死锁。小明的解法:给连接统一编号,按编号顺序申请(有序分配法),破坏环路等待条件。

🧠 2.2.2 存储管理:内存的精打细算

存储管理对象是内存,负责分配回收、保护、扩充。内存分系统空间(放OS)和用户空间(放用户程序)。虚拟存储器不考虑实际内存大小,容量由地址位数决定,给用户"内存比实际大"的错觉。

管理机制演化:单一连续区 → 分区 → 段页式。重点看段页式。

1. 页式存储管理

把程序逻辑空间和内存物理空间按同样大小分页,以页为单位分配。逻辑地址=(页号,位移),系统为每个进程建页表记录逻辑页到物理页的映射。访问时查页表:在内存就拼物理地址;不在就产生缺页中断,从磁盘调入。

内存没空块时按算法淘汰一页,淘汰选择不当会抖动(刚调出又调入,反复折腾)。页面调度算法:

  • 🏆 OPT(最优):淘汰不再用或最远将来才用的。理想但难实现,作对比基准
  • 🎲 RAND(随机):瞎选一个,可能选中马上要用的
  • 📤 FIFO(先进先出):淘汰内存驻留最久的。简单,但可能踢频繁使用的页;页面数增多缺页反而增多(Belady异常)
  • 📉 LRU(最近最少使用):淘汰最久没用的。较合理,实现复杂
页面调度像书架放不下要拿走哪本书:OPT是先知——知道哪本再也不看;FIFO是"最先买的先拿走"——但可能把天天翻的词典拿走了;LRU是"最久没翻过的拿走"——最贴近实际。Belady异常是FIFO的怪事:书架变大了反而更频繁地搬书,简直反直觉。

2. 段式存储管理

逻辑意义分段(主程序、子程序、数据段),以段为单位内外存交换。逻辑地址=(段号,位移),系统建段表记录段号、段长、内存起始地址、状态。段不在内存产生缺段中断。段式便于共享和保护,但每个段要连续内存,易产生碎片。

3. 段页式存储管理

段式+页式的结合:按模块分段,段内再分页,内存按定长页分配。逻辑地址=(段号,页号,页内偏移)。系统为每个进程建段表,为每段建页表。段式分配+页式使用,便于动态连接和动态分配,提高利用率。开销大,一般大型机用。

💡 秒懂技巧:页式像把书按固定厚薄切块(不管内容),段式像按章节分(逻辑完整但厚度不一),段页式是先按章节分、每章再切等厚页——既有逻辑结构又好分配。虚拟存储就是"书桌放不下整本大辞典,就翻开要看的那几页放桌上,看完换页"。

🖨️ 2.2.3 设备管理:外设的调度员

1. 数据传输控制方式

外设和内存间数据传送的四种方式,从低到高:

  • 🐌 程序控制方式:CPU启动传输然后死等设备完成。CPU利用率最低
  • 📢 中断方式:启动后CPU干别的,设备完成发中断通知。能并发,但每传一个数据都要中断CPU
  • 🚀 DMA方式:外设和内存间直接开辟数据通路,DMA控制器窃取CPU周期完成传输,大批量数据不用CPU操心
  • 🏭 通道方式:通道(IOP)是独立的小处理器,执行自己的通道程序完成内存和外设间传输。有字节多路通道、选择通道、成组多路通道三种
程序控制像你亲自盯着快递装车,一箱一箱数;中断像快递说"装好了你忙别的我喊你";DMA像雇了个搬运工直接往车上搬你不用数;通道像外包给物流公司,人家自己派车自己装,你只管下单。CPU越往后越省心。

2. 虚设备与SPOOLING技术

SPOOLING(假脱机/外部设备同时联机操作)用一道程序模拟外围控制机,把低速独占设备改造成可共享的虚设备,一台物理设备对应若干台虚拟同类设备。必须有高速大容量可随机存取的外存(磁盘)支持。

💡 秒懂技巧:SPOOLING像银行的取号机——打印机一次只能服务一个人(独占),但取号后大家先存到磁盘队列里"挂着号",打印机按号一个个处理,对用户来说"打印机随时都能用"(虚设备)。多窗口技术也是同理:一台显示器模拟多个窗口。

📁 2.2.4 文件管理:数据的安全柜

文件系统负责组织、存取、保护数据。功能:建删改文件、按名访问、决定存放位置/形式/权限、管理共享和保护保密。

1. 文件的逻辑结构

用户角度的组织形式,分无结构字符流和有结构记录文件。记录文件四种:

  • 顺序文件:记录定长按键排序,常用于批处理,查询某条性能差
  • 索引顺序文件:基于键次序+维护索引和溢出区,交互和批处理都行
  • 索引文件:按需要的属性建索引,索引本身是顺序文件
  • 直接文件(Hash文件):按物理地址随机访问,高速单条查询

2. 文件的物理结构

存储设备上的存放方法,分:

  • 顺序分配(连续分配):预先分配连续物理块。顺序存取快,但不能动态增长
  • 链接分配(串联分配):每块末尾存下一块指针。无碎片、可动态增长,但只能顺序访问、搜索慢
  • 索引分配:为每个文件建索引表记录逻辑块到物理块映射。可动态增长、可随机访问,但索引表占空间、存取要两次访盘。UNIX用三级索引结构

3. 文件存储设备管理(空闲块)

  • 索引法:把空闲块当文件用索引组织
  • 链接法:链表组织空闲块
  • 位示图法:每位对应一个物理块,0空闲1占用。字长32位管32个块,紧凑高效

4. 树型目录结构

根目录在顶层,子目录是节点,数据文件是树叶。从根开始的是绝对路径(如 c:\dos\lmouse\mouse),从当前目录开始的是相对路径(一般从..开始)。每个目录有 . (当前) 和 .. (父目录)。树型结构让每个文件路径名唯一,解决重名问题。

💡 秒懂技巧:树型目录像家谱树——根目录是老祖宗,子目录是各代子孙,文件是末端的"人"。绝对路径是从老祖宗数到这个人(完整地址),相对路径是"从我哥家往上一层就是我舅"(基于当前位置)。位示图像停车场显示屏——每车位一个灯,亮=占用灭=空闲,一眼看全。

📋 2.2.5 作业管理:从提交到完成

作业是系统为完成用户计算任务所做的工作总和。一个作业分多个作业步(编译→连接→运行),顺序执行完成一个作业。作业由程序、数据、作业说明书组成。

1. 作业四状态

  • 📥 提交:作业从输入设备进外存(输入井),信息正在进入系统
  • 🗃️ 后备:全部信息进外存后建JCB(作业控制块),系统通过JCB感知作业
  • ⚙️ 执行:被调度选中,分配资源进内存,建相应进程
  • 完成:正常运行结束,资源还没全部回收

2. 用户接口

  • 命令接口:键盘命令、作业控制命令
  • 程序接口(系统调用):编程接口,是操作系统提供给编程人员的唯一接口。分设备管理、文件管理、进程控制、进程通信、存储管理等
  • 操作环境:从命令驱动→菜单→图符→视窗
🎮 实战场景:饿了么么每天凌晨跑"昨日结算报表"批处理作业——提交(数据进磁盘)→后备(JCB就绪)→执行(调度进内存跑)→完成(输出报表、回收资源)。这就是典型的批处理作业生命周期。用户接口上,骑手App调的就是系统调用API,不是命令行。