前言
Linux 作为后端开发、运维、嵌入式领域的核心技术栈,其底层原理和核心机制是面试高频考点。本文整理了 Linux 操作系统核心知识点,涵盖进程管理、内存管理、设备管理、文件系统等核心模块,内容兼具深度与实用性,既适合面试突击背诵,也可作为日常开发查阅手册。
一、操作系统基础
1. 什么是操作系统(OS)?
-
本质:运行在计算机上的核心软件,负责管理硬件(CPU、内存、磁盘等)和软件资源(程序、数据)。
-
核心作用:屏蔽硬件层复杂性,为应用程序提供统一的抽象接口,协调资源分配与调度。
-
内核(Kernel):OS 的核心组件,负责内存管理、硬件设备管理、文件系统管理、进程调度,是应用程序与硬件的桥梁,决定系统性能与稳定性。
二、进程与线程
2. 进程、线程、协程的联系与区别
| 维度 | 进程 | 线程 | 协程 |
|---|---|---|---|
| 核心定位 | 资源分配的最小单位 | 系统调度(CPU)的最小单位 | 用户态轻量级线程,线程内调度单位 |
| 切换主体 | 操作系统 | 操作系统 | 用户程序 |
| 切换过程 | 用户态→内核态→用户态 | 用户态→内核态→用户态 | 全程用户态 |
| 切换开销 | 极大(需切换页表、内核栈) | 较小(仅切换少量寄存器) | 极小(仅保存栈和上下文) |
| 拥有资源 | 独立地址空间、文件句柄等,全局变量属于进程资源,由进程内线程共享。 | 共享进程资源,私有栈、寄存器、程序计数器 | 私有栈和上下文,共享线程资源 |
| 崩溃影响 | 不影响其他进程 | 导致整个进程崩溃 | 仅影响当前协程 |
| 通信方式 | 依赖 IPC(管道、共享内存等) | 直接读写进程数据段(全局变量) | 共享内存、消息队列 |
核心联系:1 个进程至少包含 1 个主线程,线程只能属于一个进程,协程必须依托线程存在。
3. 为什么需要线程?
-
解决进程阻塞问题:进程执行中若因 I/O 等操作阻塞,整个进程会挂起;线程引入后,同一进程内的其他线程可继续执行,提升并发效率。
-
降低开销:线程的创建、销毁、切换开销远小于进程(无需分配/回收独立地址空间)。
4. 线程的类型
-
用户级线程:由应用程序管理,无需进入内核空间,切换高效,但无法利用多核 CPU 实现真正并发(内核无感知)。
-
内核级线程:由内核管理,可分配到不同 CPU 核心,并发能力强,但切换需在用户态与内核态间切换,开销略高。
5. 并发与并行的区别
-
并发:宏观上多个任务在一段时间内同时进行,微观上同一时刻仅一个任务执行(任务交替切换,如单核 CPU 多任务)。
-
并行:宏观与微观上,多个任务均同时执行(需多核 CPU 支持,任务无抢占资源)。
6. 进程的状态与转换
-
核心状态:新建 → 就绪 → 运行 → 阻塞 → 消亡
-
新建:进程刚创建,未加载到主存。
-
就绪:具备运行条件,等待 CPU 调度。
-
运行:占用 CPU 执行程序。
-
阻塞:等待某事件(如 I/O 完成),主动放弃 CPU。
-
消亡:进程执行完毕或被撤销。
-
-
状态转换关键触发条件:
-
就绪→运行:CPU 调度空闲。
-
运行→就绪:时间片用完或有高优先级进程进入就绪态。
-
运行→阻塞:进程请求 I/O 或调用 sleep()。
-
阻塞→就绪:等待的事件完成(如 I/O 结束)。
-
-
进程控制块(PCB):进程存在的唯一标识,存储进程 PID、状态、页表、文件句柄等信息,创建进程时生成,撤销时销毁。
7. 进程间通信(IPC)方式
| 通信方式 | 核心特点 | 适用场景 |
|---|---|---|
| 无名管道(pipe) | 半双工、仅存在于内存、无文件名,仅支持亲缘进程(父子/兄弟)通信 | 父子进程数据传输 |
| 命名管道(FIFO) | 半双工、有文件名,支持无亲缘关系进程通信 | 本地非亲缘进程通信 |
| 消息队列 | 内核中的消息链表,按类型/优先级排序,克服管道无格式、容量受限问题 | 异步通信,需按类型传输数据 |
| 共享内存 | 最快的 IPC 方式,多个进程映射同一段物理内存,直接读写 | 高频、大数据量通信(需信号量同步) |
| 信号量(Semaphore) | 计数器,用于控制共享资源访问,实现进程同步互斥 | 进程间同步(如临界资源保护) |
| 信号(Signal) | 异步通知机制,传递简单事件(如 Ctrl+C 触发 SIGINT 信号) | 进程间紧急事件通知 |
| 套接字(Socket) | 支持跨主机通信,分为 TCP(流式可靠)和 UDP(数据报不可靠) | 网络通信(跨主机/本地进程) |
8. 死锁的产生与解决
-
死锁定义:多个进程互相等待对方释放资源,形成僵局,无外力干预无法继续执行。
-
四个必要条件(缺一不可):
-
互斥:资源只能被一个进程占用(不可被多个进程同时访问)。
-
不可抢占:进程占用的资源未用完不能被其他进程强制剥夺。
-
占有并等待:进程占有部分资源,同时等待其他未分配的资源。
-
环路等待:多个进程间形成首尾相接的资源请求环路。
-
-
解决方法:
-
预防:破坏任一必要条件(如一次性申请所有资源、按顺序请求资源)。
-
避免:银行家算法(预判资源分配后是否会导致死锁,安全则分配)。
-
检测与修复:定期检测死锁,通过撤销进程或剥夺资源解除死锁。
-
9. 处理机调度算法
| 算法类型 | 核心逻辑 | 特点 |
|---|---|---|
| 先来先服务(FCFS) | 按进程进入就绪队列顺序调度 | 利于长作业,短作业可能"饿死" |
| 短作业优先(SJF) | 优先调度运行时间最短的进程 | 利于短作业,长作业可能"饿死" |
| 最短剩余时间优先(SRTN) | 抢占式 SJF,新进程剩余时间更短时抢占当前进程 | 兼顾短作业与响应速度 |
| 优先级调度(PS) | 按进程优先级调度,可动态调整优先级(避免"饿死") | 灵活,需合理设置优先级 |
| 最高响应比优先(HRRN) | 响应比 = 1 + 等待时间/运行时间,优先调度响应比高的进程 | 平衡长/短作业 |
| 时间片轮转(RR) | 就绪进程按 FCFS 排队,每个进程分配固定时间片,超时则切换 | 公平,适用于分时系统 |
| 多级反馈队列(RRMF) | 多优先级队列,高优先级队列时间片短,低优先级队列时间片长,支持抢占 | 综合性能最优,主流选择 |
10. 僵尸进程与孤儿进程
-
孤儿进程:父进程退出,子进程未退出,由 init 进程(PID=1,systemd 系统中为 systemd 进程)收养,无危害。
-
僵尸进程:子进程退出,父进程未调用 wait()/waitpid() 回收其状态信息,子进程 PID 与退出状态仍占用系统资源。
-
僵尸进程危害:系统 PID 资源有限,大量僵尸进程会导致无法创建新进程。
-
解决方法:
-
父进程处理 SIGCHILD 信号,在信号处理函数中调用 wait()。
-
杀死父进程,僵尸进程转为孤儿进程后由 init 回收。
-
fork 两次,子进程成为孤儿进程,由 init 管理。
-
三、内存管理
11. 内存管理的核心功能
-
内存分配与回收:为进程分配内存,进程结束后回收内存(对应 malloc/free、new/delete)。
-
地址转换:将程序的逻辑地址(相对地址)转换为物理地址(绝对地址)。
-
内存共享与保护:实现多个进程共享代码/数据,通过硬件(上下界寄存器)或软件限制内存访问范围。
-
内存扩充:通过虚拟内存技术,将磁盘空间作为内存扩展,支持运行比物理内存大的程序。
12. 内存分配方式
(1)连续分配
-
单一连续存储管理:内存分为系统区和用户区,适用于单用户单任务系统,内存利用率低。
-
分区式存储管理:
-
固定式分区:内存划分为固定大小分区,产生内碎片(分区内未利用空间)。
-
动态分区:按需分配连续内存,产生外碎片(分区间未利用空间)。
-
-
分配算法:最先适应、最佳适应、最坏适应。
(2)非连续分配
-
分页存储管理:
-
原理:将逻辑内存与物理内存划分为固定大小的"页",进程页面可离散存储在物理内存中。
-
地址转换:逻辑地址 = 页号 + 页内偏移,通过页表映射到物理页号,物理地址 = 物理页号×页大小 + 页内偏移。
-
优点:无外碎片,内存利用率高;缺点:可能产生内碎片,传统分页需全部装入内存(请求分页可实现部分装入)。
-
-
分段存储管理:
-
原理:按程序逻辑划分"段"(如代码段、数据段),段大小不固定,每段连续存储,段间离散。
-
优点:无内碎片,便于共享与保护;缺点:有外碎片,需内存紧缩。
-
-
段页式存储管理:先分段,再分页,结合分段与分页优点,是主流内存管理方式。
13. 虚拟内存技术
-
核心概念:基于局部性原理,程序运行时无需全部装入内存,仅装入当前所需页面;未命中时触发缺页中断,调入所需页面,实现"逻辑内存扩展"。
-
局部性原理:
-
时间局部性:近期访问过的数据/指令可能再次访问(如循环)。
-
空间局部性:访问某地址时,其附近地址可能被访问(如数组)。
-
-
虚拟内存实现方式:
-
请求分页存储管理:分页基础上增加请求调页与页面置换功能。
-
请求分段存储管理:分段基础上增加请求调段与分段置换功能。
-
-
页面置换算法:
-
先进先出(FIFO):淘汰内存中最久的页面,易产生"Belady 异常"。
-
最近最久未使用(LRU):淘汰最久未访问的页面,性能优但实现复杂。
-
最近未使用(NRU):淘汰近期未访问的页面,实现简单。
-
最佳置换算法(OPT):淘汰未来最久不使用的页面,理想算法(无法实现)。
-
14. 快表与多级页表
-
快表(TLB):高速缓冲存储器,存储页表的常用映射项,加速地址转换(访问快表速度远高于内存)。
-
多级页表:将页表分级存储,仅加载当前所需级别的页表项,减少内存占用(时间换空间)。
四、上下文切换与系统调用
15. 上下文切换
-
上下文:CPU 寄存器 + 程序计数器(PC),是 CPU 运行任务的必要环境。
-
切换流程:保存当前任务上下文 → 加载新任务上下文 → 跳转到新任务执行。
-
切换类型:
-
进程上下文切换:切换不同进程,需切换地址空间、页表等,开销最大。
-
线程上下文切换:同一进程内线程切换,共享地址空间,仅切换私有栈/寄存器,开销小。
-
中断上下文切换:响应硬件中断,仅涉及内核态上下文,开销中等。
-
16. 系统调用
-
核心概念:用户态进程请求内核态服务的接口(如文件操作、内存分配),是用户态与内核态的桥梁。
-
流程:用户态 → 触发软中断(int 0x80 或 syscall) → 切换到内核态 → 执行内核服务 → 切换回用户态。
-
与普通函数调用区别:系统调用涉及特权级切换(用户态→内核态),普通函数调用仅在用户态执行。
五、设备管理与 I/O
17. 设备分类与管理功能
-
设备分类(按共享属性):独占设备(如打印机)、共享设备(如磁盘)、虚拟设备(通过假脱机技术将独占设备改为共享)。
-
核心功能:设备分配与回收、设备启动、虚拟设备实现、I/O 控制。
18. I/O 控制方式
-
程序直接控制方式:CPU 循环查询设备状态,效率极低。
-
中断控制方式:设备完成 I/O 后向 CPU 发中断,CPU 暂停当前任务处理中断,效率中等。
-
DMA 方式:直接内存访问,设备与内存直接传输数据,仅在传输开始和结束时需要 CPU 介入,效率高。
-
通道控制方式:通过专用通道硬件管理 I/O,支持多设备并行传输,CPU 干预极少。
19. 磁盘调度算法
-
核心目标:减少磁头寻道时间,提升磁盘 I/O 效率。
-
常用算法:
-
先来先服务(FCFS):按请求顺序处理,寻道时间长。
-
最短寻道时间优先(SSTF):优先处理磁头最近的请求。
-
扫描算法(SCAN,电梯算法):磁头双向移动,处理途经请求。
-
循环扫描(C-SCAN):磁头单向移动,到达尽头后直接返回起始端。
-
LOOK/C-LOOK:优化版 SCAN/C-SCAN,磁头无需走到尽头。
-
六、核心补充知识点
20. 同步/异步与阻塞/非阻塞
-
同步:请求方需等待响应后再继续执行(如阻塞 I/O、非阻塞 I/O 的轮询)。
-
异步:请求方发送请求后可执行其他任务,响应通过通知机制返回(如异步 I/O)。
-
阻塞:请求未完成时,当前线程被挂起,无法执行其他任务。
-
非阻塞:请求未完成时,线程不挂起,直接返回"未完成"状态。
-
最优组合:异步非阻塞(高并发场景主流选择)。
21. 零拷贝技术
-
传统 I/O 问题:数据需经过"磁盘→内核缓冲区→用户缓冲区→socket 缓冲区",多次拷贝与状态切换,开销大。
-
零拷贝实现方式:
-
mmap:内核缓冲区与用户缓冲区映射,减少一次 CPU 拷贝。
-
sendfile:数据直接从内核缓冲区拷贝到 socket 缓冲区,仅 2 次状态切换、1 次 CPU 拷贝。
-
sendfile+DMA 收集:数据描述信息传递,0 次 CPU 拷贝,仅涉及 DMA 拷贝,效率最高。
-
22. 缓存(Cache)与缓冲(Buffer)的区别
-
缓存(Cache):加速 CPU 与内存的数据交换,存储近期访问的数据(如 CPU 多级缓存、页缓存)。
-
缓冲(Buffer):加速内存与 I/O 设备的数据交换,暂存待写入/读取的数据(如磁盘缓冲区)。
23. 软中断与硬中断的区别
-
硬中断:由硬件设备引发(如磁盘 I/O 完成、键盘输入),可屏蔽,处理优先级高。
-
软中断:由程序或内核触发(如系统调用、信号、内核定时器),可屏蔽,用于处理硬中断的后续工作(中断下半部),优先级低于硬中断。
总结
本文覆盖了 Linux 操作系统面试的核心知识点,从进程、内存、设备、I/O 等核心模块展开,结构清晰、重点突出。建议结合实际场景理解(如多线程与多进程的选型、死锁排查、虚拟内存原理),面试时不仅要记住结论,更要掌握底层逻辑与应用场景。
如果本文对你有帮助,欢迎点赞、收藏、转发,也可在评论区交流补充~