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

下面是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,cmd 或 top 查看。

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

3)实战:查看进程状态

bash 复制代码
# 启动一个 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 进程优先级
se CFS 调度实体
cgroup 进程所属的 cgroup

5)练习题

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

2.2 调度器 (CFS - Completely Fair Scheduler)

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


1)CFS 基本原理

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

示意图:

css 复制代码
             [进程 B: vruntime=5]
                /            \
[进程 A:2]                      [进程 C:8]

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


2)负载相关指标

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

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

  • 经验判断:

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

    bash 复制代码
    cat /proc/schedstat | head

    或

    bash 复制代码
    sar -q 1 3

3)优先级和 nice 值

类型 范围 默认值
nice 值 -20 ~ +19 0
优先级(PR) 实时调度:1~99,普通调度:100+nice+20 普通进程约 120
bash 复制代码
# 启动一个高优先级任务
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 调度。
bash 复制代码
# 将进程切换为实时调度
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

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

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

重点字段:

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

3)perf top

实时分析 函数级 CPU 热点。

bash 复制代码
sudo perf top

输出示例:

css 复制代码
  20.54%  [kernel]  [k] copy_user_generic_unrolled
  15.12%  libc.so.6 [.] memcpy
   8.73%  my_app    [.] process_data

4)ftrace / bpftrace

ftrace 查看调度事件
bash 复制代码
# 启用调度跟踪
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 观察调度延迟
bash 复制代码
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:

    bash 复制代码
    sysctl kernel.nmi_watchdog=1
  3. 检查 dmesg 输出:

    bash 复制代码
    soft lockup - CPU#3 stuck for 23s!

Day 2 练习


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

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

    bash 复制代码
    yes > /dev/null &
  2. 运行:

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


练习 2:模拟 soft lockup 并定位

c 复制代码
// lockup.c
#include <unistd.h>
int main() {
    while(1) {}  // 无限循环,模拟 lockup
    return 0;
}
bash 复制代码
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 阻塞。使用 iotop、iostat 排查磁盘瓶颈。


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

  • dmesg 报错中明确提示:

    bash 复制代码
    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 值。

bash 复制代码
sudo sysctl kernel.perf_event_paranoid=1

Day 2 总结

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

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

相关推荐
Fcy64814 分钟前
Linux下 进程间关系与守护进程
linux·运维·服务器·守护进程
码农小韩43 分钟前
Linux驱动理论(二)——Linux字符设备驱动
linux·嵌入式软件开发·linux操作系统·linux应用开发·linux驱动理论
well06121 小时前
Linux粘滞位与Makefile机制深度解析
linux·运维·服务器
再写一行代码就下班1 小时前
linux sh脚本在windows修改导致无法使用解决方式
java·linux·centos
额额额对了1 小时前
SPI通信
linux·c语言·汇编·单片机·嵌入式硬件·arm
子木HAPPY阳VIP2 小时前
Ubuntu 关闭防火墙操作步骤
linux·运维·ubuntu
王振超wzc2 小时前
嵌入式开发环境搭建--WM软件安装,Ubuntu操作系统安装
linux·运维·ubuntu
GeW3 小时前
制造强国底座:Linux与数据库驱动的新型工业基础设施
linux
xiaoye-duck4 小时前
《Linux 网络编程》深入理解 IO 多路复用:select 函数详解与 Echo 服务实战
linux·网络
Tairitsu_H4 小时前
[Linux系统] 命令行参数 | 环境变量 | 程序地址空间
linux·环境变量·命令行参数·程序地址空间