Linux 基础知识 - CPU 上下文切换之问题排查
系统上下文切换数量如何判断是否正常?
在 Linux 系统中,CPU 的上下文切换(context switch)数量并没有一个严格的“正常”标准,因为上下文切换的频率与系统的工作负载、应用程序类型和配置密切相关。然而,可以通过以下几点来分析上下文切换是否在合理范围内:
与 CPU 核心数对比
如果上下文切换的数量除以 CPU 核心数得到的平均值比较高(例如,每个核心每秒数万次切换),需要检查是否有过多线程在竞争。
CPU 使用率是否受影响
如果上下文切换数量很高,但 CPU 的用户态和内核态使用率也同时很高,可能说明系统陷入了资源竞争。
系统响应是否正常
如果上下文切换的数量增多伴随着明显的系统卡顿、进程阻塞或服务延迟,则说明系统存在资源竞争。
如何统计系统范围一段时间内,上下文切换比较高的进程?
pidstat 是 sysstat 工具包的一部分,可以按进程统计上下文切换次数(包括自愿和非自愿切换)。
pidstat -w 1 3示例输出:
Linux 3.10.0-1160.119.1.el7.x86_64 (tdc-55) 11/20/24 _x86_64_ (48 CPU) 12:44:45 UID PID cswch/s nvcswch/s Command
12:44:46 0 1 0.96 0.00 systemd
12:44:46 0 6 1.92 0.00 ksoftirqd/0
12:44:46 0 9 194.23 0.00 rcu_sched
12:44:46 0 19 0.96 0.00 migration/2
12:44:46 0 25 0.96 0.00 ksoftirqd/3
12:44:46 0 40 0.96 0.00 ksoftirqd/6
12:44:46 0 50 0.96 0.00 ksoftirqd/8
12:44:46 0 59 0.96 0.00 migration/10
12:44:46 0 60 7.69 0.00 ksoftirqd/10
其中字段说明如下:
•
cswch/s:每秒自愿上下文切换次数。•
nvcswch/s:每秒非自愿上下文切换次数。•
Command:进程名称。
通过观察 cswch/s 和 nvcswch/s 值,我们可以确定上下文切换较高的进程。
如果对单个进程感兴趣,可以直接查看 /proc/[pid]/status 中的 voluntary_ctxt_switches 和 nonvoluntary_ctxt_switches 字段,例如:
cat /proc/1/status
...
voluntary_ctxt_switches: 7014781
nonvoluntary_ctxt_switches: 173757如何找出一个进程的 context switch 比较高的原因?
找出一个进程上下文切换(context switch)较高的原因需要结合上下文切换的类型、进程的行为、系统资源状况等多个方面进行分析。以下是具体的排查方法和常见原因:
判断上下文切换类型
grep 'voluntary_ctxt_switches' /proc/<pid>/status
grep 'nonvoluntary_ctxt_switches' /proc/<pid>/status如果某一类型上下文切换值较高,可以针对该类型进行进一步分析。
分析自愿上下文切换(Voluntary Context Switch)
常见原因
• 频繁等待 I/O:进程正在等待磁盘或网络 I/O 完成,主动让出 CPU。
• 锁竞争:多线程程序中,线程因获取锁失败而主动阻塞。
• 资源不可用:进程等待资源(如信号、管道数据、文件描述符)可用。
排查方法
• 使用 strace 分析系统调用:
strace c -p <pid>查看进程频繁调用的系统调用,是否存在大量 read、write、poll 或 futex 操作。
• 使用
iotop检查I/O活动:
iotop -o -p <pid>查看是否有大量的磁盘 I/O 活动。
• 使用
perf检查锁竞争:
perf record -e sched:sched_switch -p <pid> sleep 5
perf report查看是否因锁竞争导致频繁的上下文切换。
分析非自愿上下文切换(Non-Voluntary Context Switch)
常见原因
• CPU 时间片用尽:进程运行时占用 CPU 时间片,被系统调度器强制切换。
• 高优先级进程抢占:系统中其他高优先级进程抢占了 CPU 资源。
• 核争用:在多核环境下,进程频繁被调度到不同的 CPU 核上运行。
排查方法
• 检查进程的 CPU 使用情况:
使用 top 或 pidstat 查看进程的 CPU 占用是否异常。
pidstat -u 1 -p <pid>• 观察系统负载:
使用 htop 或 uptime 查看是否有高负载进程导致频繁抢占。
• 使用
perf sched分析调度器行为:
perf sched record sleep 5
perf sched latency查看调度器是否频繁切换进程,以及其他高优先级进程的抢占行为。
结合应用场景分析
网络相关进程
网络应用通常涉及大量 I/O,可能会有较高的自愿上下文切换。
• 使用 ss 或 netstat 检查是否存在大量连接:
ss -s多线程程序
多线程程序可能因锁竞争导致高上下文切换。我们使用 perf 查看锁竞争情况:
perf lock record -p <pid>
perf lock report示例输出:
# Usage Time Caller
contended total wait max wait
-------------------------------------------------
1 100 5.678 ms 1.123 ms mutex_lock+0x12
2 80 4.321 ms 0.954 ms pthread_mutex_lock+0x21
3 50 3.210 ms 1.002 ms futex_wait+0x33内核需要开启
CONFIG_LOCKDEP和CONFIG_LOCK_STAT这两个参数。
大量进程竞争
如果系统中运行了大量的进程,可能导致 CPU 资源不足,进而增加非自愿上下文切换。我们可以使用 ps 或 top 检查系统中运行的进程总数:
ps -e | wc -l总结和优化思路
分析步骤:
• 确认上下文切换类型(自愿/非自愿)。
• 排查高 I/O、锁竞争、高负载等可能原因。
• 结合应用程序的行为(如 I/O 密集或计算密集)调整代码逻辑或系统配置。
优化上下文切换整体思路
• 减少 I/O 阻塞:使用异步 I/O 或优化磁盘性能。
• 减少锁竞争:优化多线程代码,使用更高效的锁机制(如 spinlock)。
• 优化调度优先级:根据进程重要性设置更高的调度优先级:
renice -n -5 -p <pid>• 降低系统负载:检查并减少无关的高负载进程。