5 天学习 Linux Kernel 主要原理 | Day 2:Linux 进程管理与调度

155 阅读6分钟

下面是Day 2 进程管理与调度的学习内容,包含讲解、演示命令、案例、练习、FAQ,让你从概念到排查问题逐步掌握。


Day 2:Linux 进程管理与调度(Process Management & Scheduler)

目标:掌握 Linux 进程的核心概念、CFS 调度原理、进程优先级及调度策略,学会使用调试工具定位 CPU 性能瓶颈和 lockup 问题。


2.1 进程与线程(Process vs Thread)

了解 Linux 如何管理进程、线程,掌握 task_struct 的关键概念。


1)进程与线程的基本定义

  • 进程(Process) 操作系统为正在运行的程序分配的独立资源单元。包括:

    • 独立的虚拟内存空间
    • 打开的文件描述符表
    • 安全上下文(UID、GID、capabilities 等)
  • 线程(Thread) 运行在同一进程内的轻量级执行单元,共享虚拟内存空间,但有自己独立的:

    • 栈空间
    • 程序计数器
    • 调度信息

Linux 中的特殊点:

  • Linux 不区分严格意义上的“进程”和“线程”,两者都由 task_struct 表示。
  • 内核通过 clone() 系统调用创建子任务,设置不同的 CLONE_* 标志位实现线程或进程的效果。

2)进程状态详解

ps -eo pid,state,cmdtop 查看。

状态名称含义常见场景
RRunning/可运行当前正在 CPU 上运行,或在运行队列中等待高负载 CPU-bound 任务
SInterruptible Sleep可中断睡眠,等待事件或信号唤醒网络 I/O,select/poll
DUninterruptible Sleep不可中断睡眠,通常等待 I/O 完成磁盘 I/O,NFS 卡住
ZZombie僵尸进程,进程已退出但父进程未回收父进程编写 Bug
TStopped/Traced停止运行,或被调试器挂起Ctrl+Zptrace 调试

3)实战:查看进程状态

# 启动一个 sleep 进程
sleep 300 &
ps -o pid,ppid,state,cmd -p $!

# 模拟停止进程
kill -STOP $!
ps -o pid,state,cmd -p $!

# 恢复运行
kill -CONT $!
ps -o pid,state,cmd -p $!

4)task_struct 关键字段

每个进程在内核中都由一个 task_struct 结构表示,位于 include/linux/sched.h。 核心字段:

字段作用
pid进程 ID
state当前进程状态
mm内存管理信息,指向 mm_struct
files文件描述符表
prio / static_prio进程优先级
seCFS 调度实体
cgroup进程所属的 cgroup

5)练习题

  1. 使用 ps 找出系统中所有状态为 D 的进程。
  2. 写一个 Python 脚本创建 5 个线程,用 ps -Lf <PID> 查看线程信息。
  3. 通过 cat /proc/<PID>/status 找到该进程的 PPidThreads 字段。

2.2 调度器 (CFS - Completely Fair Scheduler)

Linux 默认使用 CFS(完全公平调度器),目标是 公平分配 CPU 时间


1)CFS 基本原理

  • CFS 将所有可运行进程放入红黑树(RB-tree)
  • 红黑树的 key:vruntime(虚拟运行时间),运行时间短的任务优先。
  • 当 CPU 空闲时,调度器选择 vruntime 最小 的进程运行。

示意图:

             [进程 B: vruntime=5]
                /            \
[进程 A:2]                      [进程 C:8]

运行后更新 vruntime,树自动调整,保证所有进程得到公平 CPU 时间


2)负载相关指标

load average(平均负载)
  • 使用 uptimesar -q 查看:

    uptime
    # 输出示例: load average: 3.25, 2.95, 2.88
    
  • 含义:在给定时间窗口内,处于 R(运行)或 D(不可中断睡眠) 状态的平均进程数。

  • 经验判断:

    • Load ≈ CPU 核心数:正常。
    • Load ≫ CPU 核心数:CPU 或 I/O 瓶颈。
Run Queue(运行队列)
  • 查看当前排队进程数:

    cat /proc/schedstat | head
    

    sar -q 1 3
    

3)优先级和 nice 值

类型范围默认值
nice 值-20 ~ +190
优先级(PR)实时调度:1~99,普通调度:100+nice+20普通进程约 120
# 启动一个高优先级任务
nice -n -10 dd if=/dev/zero of=/dev/null &
# 调整优先级
renice -n 5 -p <PID>

4)实时调度(Real-time scheduling)

  • SCHED_FIFO:先进先出,无时间片。
  • SCHED_RR:轮转,带时间片。
  • SCHED_OTHER:普通 CFS 调度。
# 将进程切换为实时调度
sudo chrt -f -p 10 <PID>
chrt -p <PID>

风险提示:实时任务可能导致系统卡死,测试环境操作!


2.3 调试与工具


1)top/htop/ps

  • top:查看实时 CPU 占用。

    • 重点字段

      • %CPU:单核为 100%
      • NI:nice 值
      • PR:优先级
      • S:进程状态
    • 快捷键H 显示线程,P 按 CPU 排序。

  • htop:更直观,支持交互调整优先级。


2)pidstat

# 每秒刷新一次,显示所有进程 CPU 使用率
pidstat 1

# 查看某个 PID 的详细信息
pidstat -p <PID> 1

重点字段:

  • %usr:用户态 CPU 占比
  • %system:内核态 CPU 占比
  • %wait:等待 I/O 时间

3)perf top

实时分析 函数级 CPU 热点

sudo perf top

输出示例:

  20.54%  [kernel]  [k] copy_user_generic_unrolled
  15.12%  libc.so.6 [.] memcpy
   8.73%  my_app    [.] process_data

4)ftrace / bpftrace

ftrace 查看调度事件
# 启用调度跟踪
echo function > /sys/kernel/debug/tracing/current_tracer
echo 1 > /sys/kernel/debug/tracing/tracing_on
sleep 2
echo 0 > /sys/kernel/debug/tracing/tracing_on
cat /sys/kernel/debug/tracing/trace
bpftrace 观察调度延迟
sudo bpftrace -e 'tracepoint:sched:sched_switch { printf("%d -> %d\n", args->prev_pid, args->next_pid); }'

5)Soft Lockup / Hard Lockup 排查

症状:系统卡死或响应极慢。

  • Soft lockup:CPU 长时间未调度。
  • Hard lockup:NMI 中断丢失。
排查路径:
  1. 查看 /proc/softirqs/proc/interrupts

  2. 启用 NMI watchdog:

    sysctl kernel.nmi_watchdog=1
    
  3. 检查 dmesg 输出:

    soft lockup - CPU#3 stuck for 23s!
    

Day 2 练习


练习 1:使用 pidstat 分析 CPU 占用

  1. 启动一个高 CPU 占用程序:

    yes > /dev/null &
    
  2. 运行:

    pidstat 1
    
  3. 找出刚才的高 CPU 占用进程并记下 PID。


练习 2:模拟 soft lockup 并定位

// lockup.c
#include <unistd.h>
int main() {
    while(1) {}  // 无限循环,模拟 lockup
    return 0;
}
gcc lockup.c -o lockup
./lockup &
  • 检查 dmesg 是否有 soft lockup 报告。
  • 使用 perf top 查看 CPU 消耗。

练习 3:调整进程优先级

  1. 启动两个 yes 进程。
  2. renice 将一个进程的 nice 值调低(-10)。
  3. top 观察调度变化。

Day 2 FAQ


Q1:load average 一直很高,但 CPU 使用率不高? A:可能是 D 状态进程积压,表示 I/O 阻塞。使用 iotopiostat 排查磁盘瓶颈。


Q2:如何判断是软 lockup 还是硬 lockup?

  • dmesg 报错中明确提示:

    soft lockup - CPU#2 stuck for 22s!
    hard lockup - CPU#0 NMI watchdog
    

Q3:nice 值调节对实时进程有效吗? A:不生效。实时任务使用 chrt 控制。


Q4:僵尸进程如何清理? A:杀死父进程,或修改父进程代码正确回收子进程。


Q5:perf 需要特殊权限吗? A:需要 root 或调整 /proc/sys/kernel/perf_event_paranoid 值。

sudo sysctl kernel.perf_event_paranoid=1

Day 2 总结

  1. 进程管理核心:task_struct、进程状态、线程与进程的关系。
  2. CFS 调度器通过红黑树保证公平性。
  3. 负载排查核心指标:load average、Run Queue、进程优先级。
  4. 工具组合:toppidstatperf topftrace/bpftrace
  5. Soft/Hard lockup 是严重 CPU 问题,需要 NMI watchdog 配合定位。

下一步(Day 3 预告): 将学习 内存管理与 OOM 问题排查,掌握 sar -rslabtopvmstat/proc/meminfo 等工具,并模拟 OOM 崩溃。