news 2026/7/22 4:48:46

Linux 性能实战 | 第 8 篇 上下文切换、内核线程与调度延迟

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux 性能实战 | 第 8 篇 上下文切换、内核线程与调度延迟

Linux 性能实战 | 第 8 篇 上下文切换、内核线程与调度延迟 🐢

🔗 上下文切换:CPU 的“换挡”开销

在上一章中,我们探讨了调度器如何通过进程迁移来实现 CPU 负载均衡。我们提到了迁移是有成本的,这个成本的核心就是上下文切换 (Context Switch)

想象一下你正在专注地写一份复杂的代码(执行一个进程),这时突然来了一个紧急电话(中断),你不得不放下手头的工作,记录下当前的思路(保存现场),然后去处理电话(切换到内核态处理中断)。打完电话后,你还需要回忆刚才写到哪里了(恢复现场),才能继续编程。这个“放下-切换-恢复”的过程,就是一次上下文切换。

对 CPU 而言,上下文切换意味着:

  1. 保存当前进程/线程的“快照”:包括 CPU 寄存器(程序计数器、栈指针等)、进程状态、内存管理信息等。
  2. 加载下一个进程/线程的“快照”到 CPU 寄存器中。
  3. 刷新 TLB (Translation Lookaside Buffer):导致虚拟地址到物理地址的缓存失效。
  4. CPU 缓存失效:新进程的代码和数据很可能不在 CPU 的 L1/L2/L3 缓存中,需要从更慢的内存中重新加载。

一句话总结:上下文切换是必要的“恶”。没有它,多任务系统无法工作。但过于频繁的切换,就像一个员工不停地在多个任务间来回切换,大部分时间都浪费在了“切换”本身,而不是真正地“执行”任务,导致系统整体效率大幅下降。


🤔 什么时候会发生上下文切换?

上下文切换主要分为三类:

1. 进程上下文切换 (Process Context Switch)

这是开销最大的一种切换。它不仅涉及到内核态和用户态的切换,还涉及到虚拟内存空间的切换。

  • 时间片用完:CFS 调度器为了“公平”,会中断当前进程,让给vruntime更小的进程。
  • 进程阻塞:当进程需要等待某个资源时,如等待磁盘 I/O、等待网络数据、或者通过sleep主动挂起,它会被置为INTERRUPTIBLEUNINTERRUPTIBLE状态,从而触发调度,让出 CPU。
  • 更高优先级的进程就绪:一个实时进程(如SCHED_RR)变为可运行状态,会立即抢占当前正在运行的普通进程。

2. 线程上下文切换 (Thread Context Switch)

当同一进程内的两个线程之间发生切换时,因为它们共享同一个虚拟内存空间,所以切换时不需要更换页表,TLB 也不会被完全刷新。因此,它的开销比进程上下文切换要小得多。

3. 中断上下文切换 (Interrupt Context Switch)

为了快速响应硬件事件(如网卡收到数据包、硬盘完成读写),CPU 会暂停当前运行的进程,切换到内核态去执行一个中断服务程序 (Interrupt Service Routine, ISR)

中断上下文的切换非常快,因为它只涉及少量内核信息的保存和恢复,不涉及用户进程。但它会打断正常进程的执行,如果中断过于频繁,也会严重影响系统性能。


🛠️ 实战:定位上下文切换元凶

场景:一个高并发的 Web 服务器,在压力测试期间,top显示系统 CPU 使用率并不高(例如,us+sy只有 30%),但load average却异常地高,并且服务响应延迟(RT)剧增。

1. 初步诊断:vmstat

vmstat是快速发现上下文切换问题的利器。

# 每秒输出一次报告vmstat1

输出

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 0 123456 10240 567890 0 0 0 20 1024 200000 15 15 70 0 0 2 0 0 123450 10240 567892 0 0 0 30 1280 250000 18 17 65 0 0 1 0 0 123440 10240 567898 0 0 0 25 1150 220000 16 16 68 0 0

关注两列:

  • cs(context switch):每秒上下文切换的次数。这个值通常在几千到几万是正常的。但如果飙升到几十万甚至上百万,就表明系统存在严重的调度问题。
  • in(interrupt):每秒中断的次数。

在这个案例中,cs高达 20 多万,显然是问题的根源。CPU 的大部分时间都花在了“换挡”上,而不是在执行应用代码(us)或内核代码(sy)。

2. 深入分析:pidstat

找到了问题,下一步就是定位是哪个进程导致的。pidstatsysstat工具包中的一员,专门用于分析进程级别的统计信息。

# -w: 显示上下文切换信息# -p ALL: 监控所有进程# 1: 每秒输出一次pidstat -w -p ALL1

输出

Linux 5.4.0-100-generic (hostname) 01/31/26 _x86_64_ (8 CPU) 10:30:01 UID PID cswch/s nvcswch/s Command 10:30:02 1000 12345 150000.00 5.00 nginx 10:30:02 0 54321 200.00 10.00 kworker/u16:0 10:30:02 1001 9876 10.00 0.00 redis-server ...

关注两列:

  • cswch/s(voluntary context switches)自愿上下文切换。通常是因为进程等待资源(如 I/O)而主动放弃 CPU。如果这个值很高,说明应用可能存在大量的 I/O 等待或者同步锁竞争。
  • nvcswch/s(non-voluntary context switches)非自愿上下文切换。通常是因为时间片用完,或者被更高优先级的进程抢占。如果这个值很高,说明 CPU 正在被多个活跃进程激烈争抢。

pidstat的输出中,我们一目了然地看到nginx进程(PID 12345)每秒产生了 15 万次自愿上下文切换。这说明nginx的 worker 进程在疯狂地等待某个资源,导致它们不断地被挂起和唤醒。

可能的原因

  • 后端服务瓶颈nginx作为反向代理,后端应用(如 PHP、Java)处理缓慢,导致nginxworker 大量阻塞在网络 I/O 上。
  • 锁竞争:应用代码中存在设计不当的全局锁,导致大量线程在等待同一个锁。
  • 连接数过多nginx配置的worker_connections过高,而系统资源(如文件描述符)不足。

通过这个线索,开发和运维团队就可以进一步深入到nginx的配置和后端应用代码中,找到最终的性能瓶颈。


👽 神秘的内核线程:kworkerksoftirqd

在使用topps时,你经常会看到一些以k开头的、方括号括起来的进程,如kworkerksoftirqd。它们是内核线程 (Kernel Threads),在后台为操作系统执行各种管理任务。

kworker:内核的“临时工”

kworker是内核工作队列(workqueue)的执行者。内核的各个子系统(如磁盘、网络、定时器)会把一些耗时较长、不能在中断上下文中完成的任务,打包成一个“工作项”,扔到工作队列里,然后由kworker线程在未来的某个时刻异步地去执行。

命名格式kworker/u<cpu_id>:<worker_id>kworker/<cpu_id>:<worker_id>

  • u表示这个kworker是非绑定的(unbound),可以在多个 CPU 核心间迁移。
  • <cpu_id>表示它主要在哪个 CPU 上活动。

如果kworker的 CPU 使用率很高,通常意味着内核正在忙于处理某些后台任务。你可以通过perf工具来追踪kworker到底在忙什么。

ksoftirqd:软中断的“清道夫”

当硬件中断(硬中断)发生得过于频繁时,为了避免长时间关中断影响系统响应,内核会将一部分耗时较长的处理工作推迟,变成软中断 (softirq)

ksoftirqd就是专门用来处理软中断的内核线程,每个 CPU 核心都有一个。如果软中断的产生速度超过了处理速度,积压的软中断就会由ksoftirqd来“兜底”处理。

命名格式ksoftirqd/<cpu_id>

如果你在top中看到si(softirq)或者ksoftirqd的 CPU 使用率很高,通常指向以下问题:

  • 网络风暴:网络收发包极其频繁,导致大量的网络软中断。
  • 内核锁竞争:内核中处理软中断的逻辑遇到了锁竞争,导致处理效率下降。

📝 总结与展望

  • 上下文切换是核心成本:过高的cs值是系统“内耗”的明确信号。使用vmstat发现问题,再用pidstat -w定位到具体进程。
  • 区分自愿与非自愿切换cswch/s高通常指向 I/O 或锁等待问题;nvcswch/s高通常指向 CPU 资源不足或争抢激烈。
  • 关注内核线程kworkerksoftirqd的高 CPU 占用率是内核层面存在瓶颈的线索,通常与 I/O 和网络活动密切相关。

下一篇预告

在本章中,我们学会了如何量化和定位上下文切换带来的性能损耗。我们不仅掌握了vmstatpidstat这两个强大的诊断工具,还认识了kworkerksoftirqd这两个重要的内核“打工人”。

在下一章,我们将继续深入 CPU 的世界,专门探讨软中断和硬中断。我们将揭示top命令中hisi的真正含义,并学习如何处理由它们引发的性能问题。敬请期待!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/21 15:21:45

【YOLOv10多模态创新改进】独家特征融合创新篇 | ICCV 2025 | 引入 FDAM 特征差异对齐模块,适合可见光与红外图像融合目标检测、多模态图像融合目标检测、多模态遥感图像分割有效涨点

一、本文介绍 🔥本文给大家介绍使用 FDAM 特征差异对齐模块改进 YOLOv10 多模态目标检测模型,可在特征融合阶段显式压缩并对齐不同模态之间的视觉差异特征,避免将冲突或歧义信息直接送入检测头。FDAM 通过局部对齐机制在通道与空间层面抑制模态特有但对检测无效的响应,通…

作者头像 李华
网站建设 2026/7/19 19:54:55

Linux 脚本案例:适用iptables构建不同场景下的防火墙规则

一、iptables 基础概念 1.1 iptables 四表五链 四表&#xff1a; filter表&#xff1a;过滤数据包&#xff08;默认表&#xff09;nat表&#xff1a;网络地址转换mangle表&#xff1a;修改数据包raw表&#xff1a;连接跟踪 五链&#xff1a; INPUT&#xff1a;进入本机的数据…

作者头像 李华
网站建设 2026/7/19 18:16:31

PHP Error: 常见错误及其解决方法

PHP Error: 常见错误及其解决方法 引言 PHP作为一种广泛使用的服务器端脚本语言,在网站开发中扮演着重要的角色。然而,在使用PHP进行编程时,难免会遇到各种错误。本文将详细介绍PHP中常见的错误类型及其解决方法,帮助开发者更好地应对这些问题。 常见PHP错误类型 1.语法…

作者头像 李华
网站建设 2026/7/21 21:39:08

已有安全措施确认(上)

网络安全已有安全措施确认已有安全措施确认是网络安全体系建设的基础复盘环节&#xff0c;指通过技术核查、配置审计、实操验证、制度核对的方式&#xff0c;对企业已部署的技术防护措施、制定的管理管控措施、落地的运营保障措施进行全面核查&#xff0c;确认其是否有效部署、…

作者头像 李华
网站建设 2026/7/4 3:18:55

从巴菲特投资看A股投资机会

从巴菲特投资看A股投资机会 关键词&#xff1a;巴菲特投资、A股市场、投资机会、价值投资、长期投资 摘要&#xff1a;本文旨在通过深入剖析巴菲特的投资理念和策略&#xff0c;探寻其对A股市场投资机会的启示。详细介绍了巴菲特投资理念的核心要素&#xff0c;分析了A股市场的…

作者头像 李华
网站建设 2026/7/22 1:14:00

【小程序毕设源码分享】基于springboot+Android的大学生勤工助学管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华