面试题精讲:操作系统

1. I/O 多路复用:select, poll 与 epoll

面试核心: 为什么 Linux 高性能网络编程(如 Redis, Nginx, Tornado)必选 epoll?

I/O 多路复用是指内核一旦发现进程指定的一个或多个 I/O 条件准备就绪(如 Socket 收到数据),它就通知该进程。

特性selectpollepoll (极致性能)
底层数据结构数组 (fd_set)链表 (pollfd)红黑树 + 就绪链表
连接数限制有限制 (通常 1024)无限制无限制
效率$O(n)$ 轮询扫描$O(n)$ 轮询扫描$O(1)$ 回调触发
内存拷贝每次调用需全量拷贝每次调用需全量拷贝利用 mmap 共享内存,减少拷贝

2. 进程调度算法

面试核心: 操作系统如何决定下一个运行谁?

  1. 先来先服务 (FCFS):最简单,但长任务在前面会引起“护卫效应”(排队时间极长)。
  2. 短作业优先 (SJF):追求最短平均等待时间。
  3. 时间片轮转 (RR)现代 OS 基础。每个进程分配一个固定时间片,用完即排到队尾,保证公平响应。
  4. 多级反馈队列 (MLFQ)终极方案。结合了上述优点,根据进程表现动态调整优先级(如 I/O 频繁的进程优先级更高)。

3. 死锁 (Deadlock)

面试核心: 发生的四个必要条件及如何破局。

  • 四个必要条件(缺一不可):
    1. 互斥:资源一次只能被一个进程占用。
    2. 请求与保持:占着碗里的,看着锅里的。
    3. 不剥夺:不能强行抢夺别人的资源。
    4. 循环等待:A 等 B,B 等 C,C 等 A。
  • 策略: * 预防:破坏上述任一条件(如规定资源请求顺序)。
    • 避免银行家算法。在分配前模拟分配,若会导致系统进入“不安全状态”则拒绝请求。

4. 程序构建:从源码到二进制

面试核心: 预处理、编译、汇编、链接的职责。

  1. 预处理 (Pre-processing):展开宏、包含头文件、删除注释。
  2. 编译 (Compilation):词法/语法分析,将代码转为汇编语言
  3. 汇编 (Assembly):将汇编转为机器码(目标文件 .o)。
  4. 链接 (Linking):把多个目标文件和库(如 libc)合并,解决符号引用。

5. 虚拟内存:分页与分段

面试核心: 为什么要离散分配内存?

  • 分页 (Paging)物理管理。将内存切成 4KB 等大小的“页”,消除外部碎片。
  • 分段 (Segmentation)逻辑管理。按代码段、堆栈段划分,方便共享和保护。
  • 缺页中断 (Page Fault):当程序访问的页面不在物理内存时,OS 会从磁盘调入。

6. 页面置换算法

面试核心: 内存满了,踢走谁最科学?

  1. FIFO (先进先出):简单但性能差。
  2. LRU (最近最久未使用)最常用。认为过去一段时间没用的,未来大概率也不用。
  3. LFU (最少使用):统计访问频率。
  4. Clock (时钟算法):LRU 的低成本近似实现。

7. 触发模式:水平触发 (LT) vs 边沿触发 (ET)

面试核心: 为什么 Nginx 使用 ET 模式?

  • 水平触发 (Level Triggered):只要缓冲区有数据,内核就一直“催”你处理。
  • 边沿触发 (Edge Triggered)只有状态变化时通知一次。
    • 优点: 减少了内核事件重复触发的次数。
    • 要求: 必须配合非阻塞 I/O,且循环读取直到返回 EAGAIN