跳到主要内容

操作系统内核原理

核心使命:操作系统是管理硬件资源、为应用程序提供抽象接口(System Calls)的核心系统软件。

1. 操作系统架构 (System Architecture)

现代 OS 采用 分层架构微内核架构

  • 内核态 (Kernel Mode):拥有 CPU 最高特权等级(Ring 0),可执行任何指令。
  • 用户态 (User Mode):特权受限(Ring 3),通过 系统调用 (System Call) 请求内核服务。
上下文切换 (Context Switch)

当进程从用户态切换到内核态,或者从一个进程切换到另一个进程时,OS 必须保存当前 CPU 寄存器的状态(PC, SP, 通用寄存器),这一过程开销巨大。

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. 初始 1 个进程。
  2. 第一个 fork():产生 1 个新进程,总计 21=22^1 = 2
  3. 第二个 fork():原有 2 个进程各产生 1 个,总计 22=42^2 = 4
  4. 第三个 fork():原有 4 个进程各产生 1 个,总计 23=82^3 = 8结论:一共产生 8 个进程。

练习 1:生产者-消费者模型实现 (C++)

题目:使用 std::mutexstd::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)

解析步骤

  1. 安全性检查:寻找一个序列,使得每个进程的需求都能被当前剩余资源 + 已分配资源满足。
  2. 逻辑推导
    • 模拟分配请求。
    • 更新 Available = Available - Request
    • 遍历进程,检查 Need <= Available
    • 若能完成,回收资源 Available = Available + Allocation
    • 如果能找出一个完整序列,则状态安全,否则不安全。