Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

R.5 易混对照

这些概念在面试与排障中最容易被混为一谈。每张表给「一句话区别 + 判据 + 常见误用」。

1. 进程与线程

项进程线程
地址空间独立共享
fd 表独立(fork 复制)共享
信号处置独立共享(掩码每线程)
栈独立内核栈 + 用户栈独立栈(默认 8 MB 虚拟)
切换成本高(页表/TLB)低(同地址空间)
崩溃影响通常只死自己整个进程退出

判据:需要隔离/独立资源 → 进程;需要共享大量数据/低切换成本 → 线程。容器是「进程 + namespace/cgroups」,不是线程。

2. 锁与同步原语

原语等待方式适用不能做什么
互斥锁 mutex睡眠临界区可能长/可能阻塞不能在信号处理器里用
自旋锁 spinlock忙等极短临界区、不可睡眠上下文持锁睡眠会死锁
信号量 semaphore睡眠/计数资源计数、生产者-消费者不保证所有权,易误用
条件变量睡眠+唤醒等某个条件成立必须配互斥锁、while
读写锁睡眠读多写少写者可能饿死
RCU无锁读读多写极少、可容忍旧值读侧不能睡眠
原子操作不等待计数/标志/无锁结构复杂逻辑易错

判据:临界区能否睡眠?能 → mutex/信号量;不能(中断/原子上下文)→ spinlock/原子;读多写少 → rwlock/RCU。

3. I/O 多路复用

机制复杂度fd 上限触发适用
selectO(n)FD_SETSIZE(常 1024)LT兼容旧代码
pollO(n)无硬上限LT少量 fd、可移植
epollO(1) 取就绪受 fd 限制LT/ET大量连接
io_uring批量提交/完成受 ring 大小完成事件高吞吐、低延迟、异步

判据:连接数上千 → epoll;要极致 IOPS/避免系统调用 → io_uring;跨平台/少量 fd → poll。

4. epoll LT 与 ET

项LT(水平触发)ET(边缘触发)
通知时机只要就绪就通知状态变化时通知一次
是否必须读完否是,读到 EAGAIN
fd 是否必须非阻塞否是
编程难度低高,易丢事件
默认epoll 默认需显式 EPOLLET

常见误用:ET 只 read 一次;ET 用阻塞 fd;ET 忘记处理 EPOLLHUP。

5. fork / vfork / clone

项forkvforkclone
地址空间COW 复制共享,子进程先运行按 flags 选择
父进程阻塞否是,直到子进程 exec/exit否
用途通用历史优化(立即 exec)线程/命名空间
风险大内存页表复制子进程改数据会破坏父进程flags 组合复杂

判据:现代代码用 fork + exec 或 posix_spawn;线程用 pthread_create(内部 clone);不要用 vfork。

6. 硬链接与软链接

项硬链接软链接
inode同一 inode新 inode,内容是路径
跨文件系统不可以可以
指向目录不允许(普通用户)可以
原文件删除仍可访问(nlink 减 1)悬空
ls -l普通文件l 类型 + ->

判据:需要同一文件多个名字 → 硬链接;需要跨 FS/目录/可悬空 → 软链接。

7. write / fsync / O_SYNC

操作保证
write数据到 page cache(可能还没下盘)
fdatasync数据 + 必要元数据到持久介质
fsync数据 + 元数据到持久介质
O_SYNC每次 write 同步完成
O_DSYNC每次 write 数据同步(元数据按需)
sync全系统回写(不等单个文件)

常见误用:write 返回就认为落盘;fsync 后忘记 fsync 目录(rename 场景)。

8. 缓冲 I/O 与直接 I/O

项缓冲 I/OO_DIRECT
经过 page cache是否
对齐要求无地址/偏移/长度按块对齐
适用通用数据库/存储引擎自管缓存
风险缓存污染/回写抖动对齐错误 EINVAL、性能反而差

判据:没有自管缓存与对齐能力,不要用 O_DIRECT。

9. malloc / brk / mmap

项说明
malloclibc 堆分配器;小块从 arena,大块可能 mmap
brk调整堆顶;连续、易碎片
mmap映射匿名页/文件;大块、可 munmap
slab内核对象缓存,不是用户态 malloc

判据:用户态用 malloc;大块/文件映射用 mmap;内核用 kmalloc/vmalloc/slab。

10. read 与 pread

项readpread
偏移使用并推进 f_pos指定偏移,不改 f_pos
多线程共享 fd互相影响安全
原子性读+推进偏移是原子的读+定位是原子的

判据:多线程读同一文件用 pread;顺序流用 read。

11. flock 与 fcntl 记录锁

项flockfcntl(F_SETLK)
粒度整个文件字节范围
继承随 fd 复制随进程(关闭任一 fd 可能释放)
网络 FS依赖实现依赖实现
用途简单互斥数据库/文件区域锁

判据:只要「单实例」用 flock;要锁文件区域用 fcntl。

12. TCP 与 UDP

项TCPUDP
连接面向连接无连接
可靠重传/排序/去重不保证
边界字节流数据报
拥塞控制有无(应用自管)
适用HTTP/SSH/DBDNS/视频/游戏/QUIC 底层

判据:需要可靠有序 → TCP;需要低延迟/自定义可靠性 → UDP + 应用层。

13. TIME_WAIT 与 CLOSE_WAIT

状态谁进入原因处理
TIME_WAIT主动关闭方等 2MSL,处理迟到报文正常;端口耗尽才调 tcp_tw_reuse
CLOSE_WAIT被动关闭方收到 FIN,应用没 close修应用;调内核无用

判据:ss -tan state time-wait 多 → 正常/端口规划;close-wait 多 → 代码 bug。

14. SO_REUSEADDR 与 SO_REUSEPORT

项SO_REUSEADDRSO_REUSEPORT
作用允许绑定 TIME_WAIT/通配地址冲突多个 socket 绑同一端口,内核负载均衡
用途服务快速重启多进程/多线程 acceptor
风险可能绑到不该绑的地址连接分布不均、迁移复杂

判据:重启报 EADDRINUSE → SO_REUSEADDR;要多 acceptor → SO_REUSEPORT。

15. 静态链接与动态链接

项静态动态
库代码复制进可执行文件运行时加载 .so
体积大小
升级需重编换 .so 即可(ABI 兼容)
依赖少ldd/RPATH/LD_LIBRARY_PATH
安全无共享可 LD_PRELOAD 打桩

判据:容器/单文件分发 → 静态(或 musl);系统库/多程序共享 → 动态。

16. syscall 与 int 0x80

项syscall(x86-64)int 0x80(32 位)
入口syscall 指令中断门
号寄存器%rax%eax
参数%rdi/%rsi/%rdx/%r10/%r8/%r9%ebx/%ecx/%edx/%esi/%edi/%ebp
性能快慢
64 位程序正确指针截断,不要用

17. CFS 与 EEVDF

项CFSEEVDF
版本2.6.23–6.56.6+
核心vruntime 红黑树lag/vslice,按延迟需求分配
调参sched_latency 等sched_base_slice 等
读旧资料仍可理解公平性注意字段/默认值变化

18. namespace / cgroup / 虚拟机

项namespacecgroup虚拟机
隔离什么看见什么(PID/网络/挂载…)用多少(CPU/内存/IO)整台硬件
内核共享共享独立
启动毫秒毫秒秒级
安全边界较弱(共享内核)资源限制强(虚拟化)

判据:容器 = namespace + cgroup + rootfs;不是轻量虚拟机。

19. iptables 与 nftables

项iptablesnftables
规则集表/链线性表/链/集合/映射
原子更新逐条nft -f 原子
多族分 iptables/ip6tablesinet 统一
语法-A/-jnft add rule

判据:新系统用 nftables;旧脚本用 iptables-nft 兼容层,逐步迁移。

20. 一张总表

问题先问
要隔离还是共享?进程/线程、容器/VM
临界区能睡眠吗?mutex vs spinlock
连接多还是少?epoll vs poll
要可靠还是低延迟?TCP vs UDP
要持久化还是只要下盘?write vs fsync
要共享内核还是独立内核?容器 vs VM

回 R.6 术语表;做题去 R.8 综合自测卷。