操作系统内核原理
核心使命:操作系统是管理硬件资源、为应用程序提供抽象接口(System Calls)的核心系统软件。
1. 操作系统架构 (System Architecture)
现代 OS 采用 分层架构 或 微内核架构。
- 内核态 (Kernel Mode):拥有 CPU 最高特权等级(Ring 0),可执行任何指令。
- 用户态 (User Mode):特权受限(Ring 3),通过 系统调用 (System Call) 请求内核服务。
2. 进程与线程管理 (Processes & Threads)
2.1 进程 (Process)
资源分配的基本单位,拥有独立的虚拟地址空间。
- PCB (Process Control Block):内核维护的进程元数据(PID, 状态, 优先级, 文件描述符表)。
2.2 线程 (Thread)
CPU 调度的基本单位,共享所属进程的内存空间。
- LWP (Light Weight Process):Linux 中的线程实现方式。
2.3 调度算法 (Scheduling)
- CFS (Completely Fair Scheduler):Linux 默认调度器,基于红黑树维护虚拟运行时间。
- 实时调度:FIFO, Round Robin。
3. 内存管理 (Memory Management)
3.1 虚拟内存 (Virtual Memory)
为每个进程提供一个连续、私有的地址空间,其本质是 页表 (Page Table) 的映射。
- MMU (Memory Management Unit):硬件级地址转换。
- TLB (Translation Lookaside Buffer):页表项的高速缓存。
3.2 分页机制 (Paging)
- 缺页异常 (Page Fault):当访问的虚拟页不在物理内存中时,触发中断由内核从磁盘调入。
- 页面置换算法:LRU (最近最少使用), FIFO, LFU。
4. 并发与同步 (Concurrency & Synchronization)
多线程环境下保护共享资源的机制:
- 互斥锁 (Mutex):睡眠等待,适合长时任务。
- 自旋锁 (Spinlock):忙等待,适合短时、内核态任务。
- 信号量 (Semaphore):PV 操作,控制资源数量。
- 死锁 (Deadlock):产生的四个必要条件(互斥、占有并等待、非抢占、循环等待)。
5. 深度例题与练习 (Exercises)
例题 1:Fork 进程计数
题目:以下程序在 Linux 下执行后,一共会产生多少个进程(包括父进程)?
#include <unistd.h>
int main() {
fork();
fork();
fork();
return 0;
}
点击查看解析 (Check Solution)
解析:
- 初始 1 个进程。
- 第一个
fork():产生 1 个新进程,总计 。 - 第二个
fork():原有 2 个进程各产生 1 个,总计 。 - 第三个
fork():原有 4 个进程各产生 1 个,总计 。 结论:一共产生 8 个进程。
练习 1:生产者-消费者模型实现 (C++)
题目:使用 std::mutex 和 std::condition_variable 实现一个简单的有界缓冲区(容量为 5)。
点击查看解析 (Check Solution)
代码实现:
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
class BoundedBuffer {
std::vector<int> buffer;
int capacity;
std::mutex mtx;
std::condition_variable not_full;
std::condition_variable not_empty;
public:
BoundedBuffer(int cap) : capacity(cap) {}
void produce(int val) {
std::unique_lock<std::mutex> lock(mtx);
not_full.wait(lock, [this] { return buffer.size() < capacity; });
buffer.push_back(val);
std::cout << "Produced: " << val << std::endl;
not_empty.notify_one();
}
int consume() {
std::unique_lock<std::mutex> lock(mtx);
not_empty.wait(lock, [this] { return !buffer.empty(); });
int val = buffer.back();
buffer.pop_back();
std::cout << "Consumed: " << val << std::endl;
not_full.notify_one();
return val;
}
};
练习 2:银行家算法 (Banker's Algorithm)
题目:给定 5 个进程和 3 类资源(A, B, C),若当前剩余资源为 (3, 3, 2),某进程请求 (1, 0, 2),如何判定该状态是否安全?
点击查看解析 (Check Solution)
解析步骤:
- 安全性检查:寻找一个序列,使得每个进程的需求都能被当前剩余资源 + 已分配资源满足。
- 逻辑推导:
- 模拟分配请求。
- 更新
Available = Available - Request。 - 遍历进程,检查
Need <= Available。 - 若能完成,回收资源
Available = Available + Allocation。 - 如果能找出一个完整序列,则状态安全,否则不安全。