← 返回首页
一、进程与线程
- 进程:资源分配的基本单位,拥有独立地址空间、文件描述符、信号处理器
- 线程:CPU 调度的基本单位,共享进程地址空间,拥有独立栈和寄存器
- 进程状态:创建 → 就绪 → 运行 → 阻塞 → 终止,就绪和运行之间由调度器切换
- 进程通信(IPC):管道(Pipe)/ 消息队列 / 共享内存(最快)/ 信号量 / Socket / 信号
- 线程同步:互斥锁(Mutex)/ 读写锁 / 条件变量 / 信号量(Semaphore)
- 协程:用户态轻量级线程,协作式调度,无内核切换开销,Go goroutine / Java 虚拟线程
- 上下文切换:保存/恢复寄存器、程序计数器、栈指针,进程切换还需切换页表(TLB 失效)
二、CPU 调度算法
- FCFS 先来先服务:简单公平,但短作业可能等待很久(护航效应)
- SJF 最短作业优先:平均等待时间最短,但可能饿死长作业
- RR 时间片轮转:每个进程分配固定时间片,适合交互式系统,时间片太小则切换开销大
- 优先级调度:高优先级先执行,可能饿死低优先级进程,解决:老化机制(动态提升优先级)
- 多级反馈队列:多个优先级队列 + 时间片递增,兼顾响应时间和吞吐量,Linux CFS 的思想基础
- CFS 完全公平调度:Linux 默认调度器,基于虚拟运行时间(vruntime),红黑树管理进程
三、内存管理
- 虚拟内存:每个进程拥有独立虚拟地址空间,通过页表映射到物理内存,实现隔离和超额分配
- 分页机制:虚拟地址 = 页号 + 页内偏移,页表将虚拟页映射到物理页框,页大小通常 4KB
- 多级页表:减少页表内存占用,x86-64 使用四级页表(PGD→PUD→PMD→PTE)
- TLB 快表:页表缓存,命中率极高(>99%),进程切换需刷新 TLB(ASID 优化可避免)
- 缺页中断:访问的页不在物理内存 → 触发缺页异常 → OS 从磁盘加载页面 → 更新页表
- 页面置换算法:OPT(理论最优)/ FIFO / LRU(最近最少使用,实际常用近似 Clock 算法)/ LFU
- 内存分配:伙伴系统(Buddy,管理物理页框)/ Slab 分配器(管理小对象,内核常用)
- 用户空间布局:代码段 → 数据段 → BSS → 堆(向上增长)→ ... → 栈(向下增长)
四、死锁
- 四个必要条件:互斥、占有并等待、不可抢占、循环等待(四个同时满足才会死锁)
- 预防:破坏任一条件,如按序申请资源(破坏循环等待)、一次性申请所有资源(破坏占有并等待)
- 避免:银行家算法,在分配前检查是否存在安全序列,不安全则拒绝分配
- 检测与恢复:资源分配图检测环路,发现死锁后终止进程或抢占资源
- 实际策略:数据库用超时+回滚;Java 用 tryLock 超时;Linux 内核用锁排序
五、文件系统
- inode:存储文件元数据(权限、大小、时间戳、数据块指针),不包含文件名
- 目录:特殊文件,存储文件名到 inode 的映射关系
- 文件分配:连续分配(快但碎片多)/ 链表分配 / 索引分配(inode 直接+间接指针)
- VFS 虚拟文件系统:Linux 统一文件系统接口,上层应用无需关心底层是 ext4/xfs/nfs
- 日志文件系统:ext4/xfs 使用日志(Journal)保证崩溃一致性,先写日志再写数据
- Page Cache:文件数据缓存在内存中,读写先经过缓存,
fsync 强制刷盘
六、IO 模型
- 阻塞 IO:read 调用阻塞直到数据就绪并拷贝到用户空间,简单但并发差
- 非阻塞 IO:read 立即返回,未就绪返回 EAGAIN,需轮询,CPU 浪费
- IO 多路复用:select(1024 限制)/ poll(无限制但遍历)/ epoll(事件驱动,O(1) 就绪通知)
- epoll:
epoll_create → epoll_ctl(注册 fd)→ epoll_wait(等待事件),LT/ET 两种模式
- 信号驱动 IO:注册信号处理函数,数据就绪时内核发送 SIGIO 信号
- 异步 IO(AIO):发起请求后立即返回,内核完成数据拷贝后通知应用,真正的异步
- 零拷贝:
sendfile / mmap,减少内核态与用户态之间的数据拷贝,Kafka/Nginx 广泛使用
七、经典面试题
- 进程 vs 线程:进程是资源分配单位(独立地址空间),线程是调度单位(共享地址空间),线程切换开销更小
- 用户态 vs 内核态:用户态受限访问,系统调用(trap)切换到内核态,中断/异常也会触发切换
- fork():创建子进程,Copy-on-Write 优化,父子进程共享页面直到写入时才复制
- 僵尸进程 vs 孤儿进程:僵尸 = 子进程退出但父进程未 wait 回收;孤儿 = 父进程先退出,子进程被 init 收养
- 内存泄漏排查:valgrind / AddressSanitizer / pmap 查看进程内存映射