以下是关于 Linux 进程调度算法、进程切换、环境变量 的系统性梳理(以 2026 年初主流 Linux 内核 6.6 ~ 6.14+ 版本为基准)。
1. Linux 进程调度算法演进(重点掌握)
| 内核时期 | 默认普通进程调度器 | 核心思想 | 主要问题/特点 | 代表版本 |
|---|---|---|---|---|
| 2.4 及以前 | O(n) 调度 | 每次扫描所有就绪队列找最高优先级 | 时间复杂度 O(n),进程多时严重抖动 | ~2.4 |
| 2.6.0 ~ 2.6.22 | O(1) 调度 | 双数组 + 优先级队列 + bitmap | 固定 140 优先级,交互性仍不足 | 2.6早期 |
| 2.6.23 ~ 6.5 | CFS (Completely Fair Scheduler) | 虚拟运行时间 vruntime + 红黑树 | 尽量让每个进程的 vruntime 接近理想值 | 2.6.23 ~ 6.5 |
| 6.6 ~ 最新 | EEVDF | Earliest Eligible Virtual Deadline First | 虚拟截止时间 + lag,解决CFS部分痛点 | 6.6+ |
2025~2026 当前主流情况:
绝大多数发行版(Ubuntu 24.04 LTS → 26.04、RHEL 9/10、Fedora 41+、Arch、Debian 13+ 等)都已经默认使用 EEVDF。
CFS vs EEVDF 核心区别(面试/面试官常问)
| 维度 | CFS (旧) | EEVDF (新) | 实际收益 |
|---|---|---|---|
| 核心数据结构 | vruntime 红黑树 | 虚拟截止时间 + lag 红黑树 | — |
| 挑选下一个任务 | 找 vruntime 最小的任务 | 找 eligible 中 virtual deadline 最早的任务 | 更可预测的延迟 |
| 延迟控制 | 依赖 sysctl_sched_latency + heuristics | 天然支持更好延迟(减少很多 hack) | 交互式任务更丝滑 |
| 饥饿问题 | 存在一定可能(vruntime 追不上) | lag > 0 的任务优先级更高,饥饿更难发生 | 公平性提升 |
| nice 值影响 | 线性影响 vruntime 增长速度 | 类似,但调度决策更精确 | — |
| 代码复杂度 | 较高(很多历史补丁) | 更简洁,减少了大量 heuristics | 维护性更好 |
一句话总结 EEVDF 比 CFS 强在哪?
“更精确的虚拟截止时间驱动 + lag 补偿机制,让低延迟和高公平性冲突更少,减少了 CFS 时代大量的调参和 hack。”
2. 进程切换(上下文切换 Context Switch)
广义上下文切换 ≈ 4 部分开销(现代机器上最耗时的通常是第2、3项)
- 用户态 → 内核态(系统调用/中断/异常)
→ 少量寄存器 + 特权级切换(~几十 ns) - 进程/线程切换(真正昂贵的部分) 步骤 保存的内容 大致耗时(单核现代 CPU) 保存用户上下文 通用寄存器、栈指针、PC、标志位等 ~100–300 ns 切换内核栈 切换到目标进程的 kernel stack ~几十 ns 切换 MMU 切换页表(CR3 寄存器)→ TLB flush 最贵 200–1000+ ns 切换 FPU/SIMD 状态 AVX-512、AMX 等(如果使用) 可达数 μs(懒切换优化后降低) 恢复目标进程上下文 逆向操作 同保存
- 内核态 → 用户态
→ iretq / sysret(几十 ns) - 缓存/TLB 失效(间接成本)
→ L1/L2 命中率下降、TLB miss 暴增,实际“感觉”延迟可达几 μs ~ 几十 μs
2025–2026 优化方向(已大规模落地):
- Lazy FPU/SIMD 切换(只在真正使用时才保存/恢复)
- TLB 批量刷新优化
- Multi-generational LRU + 更智能的页面回收
- EEVDF 本身减少不必要的抢占
3. Linux 环境变量(Environment Variables)
存储位置(从低到高)
- 内核 → execve() 时拷贝到用户栈顶
- 进程创建(fork + exec)时继承父进程的环境变量(除非刻意清空)
- 每个进程独立的内存区域(栈顶附近)
常用操作
# 查看当前 shell 的全部环境变量
env
printenv
export # 只看 export 出去的
# 查看某个变量
echo $PATH
printenv PATH
# 设置(仅当前 shell)
NAME=value
# 设置并导出给子进程
export NAME=value
NAME=value command # 仅对这条命令生效
# 永久修改(用户级别)
# bash/zsh
vim ~/.bashrc 或 ~/.zshrc
# 全局(慎用)
sudo vim /etc/environment
# 或 /etc/profile.d/*.sh
常见面试高频环境变量
| 变量名 | 典型用途 | 是否经常被修改 |
|---|---|---|
| PATH | 可执行文件搜索路径 | ★★★★★ |
| LD_LIBRARY_PATH | 动态库搜索路径(慎用) | ★★★★ |
| LD_PRELOAD | 强制加载指定共享库(调试/HOOK 神器) | ★★★ |
| LANG/LC_ALL | 语言/编码/排序规则 | ★★★ |
| TZ | 时区 | ★★ |
| EDITOR/VISUAL | 默认编辑器(crontab、git 等使用) | ★★ |
| PS1 | shell 提示符 | ★ |
| http_proxy/https_proxy | 代理 | ★★★★ |
安全相关注意点(2025–2026 视角)
- LD_PRELOAD、LD_LIBRARY_PATH 在 setuid 程序中会被自动清空(安全设计)
- 很多现代容器/沙箱会刻意清空或限制环境变量
- 尽量使用
env -i或systemd的EnvironmentFile=来精确控制
希望以上内容对你理解和面试有帮助!
如果你想深入某个点(比如 EEVDF 代码走向、上下文切换精确汇编、setuid 下的环境变量清空逻辑等),可以继续问~