讲师中心 微信公众号
AI工具推荐 视频效率加速

C++ 获取进程当前占用精确 CPU 上下文切换次数监控统计分析【干货】

小丽君_6599

小丽君_6599

发布时间:2026-05-14 12:05:10

|

818人浏览过

|

来源于php中文网

原创

Linux下读取/proc/[pid]/status可获取精确的自愿和非自愿上下文切换次数,但多线程程序需遍历/proc/[pid]/task/[tid]/status汇总各线程值;getrusage(RUSAGE_THREAD)虽快但非POSIX标准且不支持musl。

c++ 获取进程当前占用精确 cpu 上下文切换次数监控统计分析【干货】

Linux 下读取 /proc/[pid]/status 获取线程级上下文切换统计

Linux 内核从 2.6.23 起在 /proc/[pid]/status 中暴露了 voluntary_ctxt_switches 和 nonvoluntary_ctxt_switches 两个字段,它们分别代表自愿(如等待 I/O、锁)和非自愿(如时间片耗尽被抢占)的上下文切换次数。这是目前最轻量、最精确的进程级统计来源,无需 root 权限,也不依赖 perf 或 eBPF。

实操要点:

  • 必须读取目标进程每个线程的 /proc/[pid]/task/[tid]/status —— 因为 /proc/[pid]/status 只显示主线程(即 pid == tid)的值,多线程程序的总切换次数是所有线程之和
  • 字段解析需逐行扫描,不能靠固定偏移;匹配正则 ^voluntary_ctxt_switches:[[:space:]]+(\d+) 更可靠
  • 注意 /proc/[pid]/task/ 目录可能在读取过程中动态变化(线程创建/退出),建议先 readdir() 收集全部 tid 字符串,再逐个打开 status,避免 ENOENT
  • 两次采样间隔建议 ≥100ms,否则 nonvoluntary_ctxt_switches 可能为 0 —— 时间片调度精度通常为 1–15ms,太短抓不到抢占事件

用 getrusage(RUSAGE_THREAD) 获取当前线程的自愿切换数(仅限本线程)

getrusage(RUSAGE_THREAD, &ru) 在较新 glibc(≥2.27)中会填充 ru.ru_nvcsw(自愿)和 ru.ru_nivcsw(非自愿),但仅反映调用时刻该线程自启动以来的累计值,且 RUSAGE_THREAD 并非 POSIX 标准,glibc 以外的实现(如 musl)不支持。

适用场景与限制:

立即学习“C++免费学习笔记(深入)”;

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • 适合监控单线程程序或只关心主线程行为的场景;多线程下无法汇总,因为 ru_nvcsw 不包含其他线程数据
  • 返回值是整型,无溢出检查;若进程运行超数天且频繁切换,ru_nivcsw 可能溢出(32 位系统上约 42 亿次后归零)
  • 该接口开销极低(内核态直接拷贝 task_struct 字段),比反复读 proc 文件快一个数量级,适合高频采样(如每 10ms 一次)
  • 注意:getrusage(RUSAGE_SELF) 返回的是进程所有线程的总和(Linux 实现),但标准未保证此行为,不可依赖

警惕 /proc/[pid]/stat 的 cutime/cstime 误用

不少文章把 /proc/[pid]/stat 第 15–16 项(cutime 和 cstime)当作上下文切换指标,这是典型误解——它们实际表示子进程(已终止)消耗的用户态/内核态 CPU 时间(单位:clock ticks),与上下文切换完全无关。

真正相关的字段是第 42 项(num_threads)、第 43 项(itrealvalue)之后的扩展字段,但 Linux 内核并未在 stat 中导出切换计数;强行按位置读取会导致越界或解析错误。

常见错误现象:

  • 用 Python 的 psutil.Process().cpu_times().children_user 拿到的值,本质就是 cutime,不是切换次数
  • 写脚本按空格分割 /proc/[pid]/stat 并取第 42 项,结果得到的是线程数而非切换数,造成监控曲线完全失真
  • 误将 cstime 增长速率当作调度压力指标,实际上它只反映子进程历史开销,对当前进程无实时意义

C++ 封装采样逻辑时必须处理的三个边界条件

直接裸读 proc 文件或调用 getrusage 容易在线上环境崩溃或返回脏数据。关键防御点:

  • proc 文件路径拼接前,必须用 std::to_string(pid) 而非 std::sprintf 或字符串流 —— 若 pid 为负(如传入错误句柄),前者抛异常,后者生成非法路径如 /proc/-1/status,导致 open() 返回 ENOENT 而非更明确的错误
  • 读 /proc/[pid]/task/ 目录时,readdir() 返回的 d_name 可能含非数字字符(如 .、..、status),必须用 std::all_of(d_name, ::isdigit) 过滤,否则 open("/proc/123/task/status/status") 会静默失败
  • 两次采样间若进程退出,/proc/[pid] 目录消失,stat() 返回 ESRCH;此时应立即停止该 PID 的监控任务,而不是重试或忽略 —— 否则后续所有读取都无效

真实生产环境中,nonvoluntary_ctxt_switches 突增往往意味着 CPU 资源争抢或调度延迟,但它的数值本身没有绝对阈值;必须结合同进程的 voluntary_ctxt_switches 比例、CPU 利用率、以及线程栈深度一起看,单独看一个数容易误判。

热门AI工具

更多
创客贴AI

创客贴AI是一款AI图像与设计工具,AI辅助的智能在线设计工具。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

相关专题

更多
C语言变量命名
C语言变量命名

c语言变量名规则是:1、变量名以英文字母开头;2、变量名中的字母是区分大小写的;3、变量名不能是关键字;4、变量名中不能包含空格、标点符号和类型说明符。php中文网还提供c语言变量的相关下载、相关课程等内容,供大家免费下载使用。

3529

2023.06.20

c语言入门自学零基础
c语言入门自学零基础

C语言是当代人学习及生活中的必备基础知识,应用十分广泛,本专题为大家c语言入门自学零基础的相关文章,以及相关课程,感兴趣的朋友千万不要错过了。

2408

2023.07.25

c语言运算符的优先级顺序
c语言运算符的优先级顺序

c语言运算符的优先级顺序是括号运算符 > 一元运算符 > 算术运算符 > 移位运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符。本专题为大家提供c语言运算符相关的各种文章、以及下载和课程。

1360

2023.08.02

c语言数据结构
c语言数据结构

数据结构是指将数据按照一定的方式组织和存储的方法。它是计算机科学中的重要概念,用来描述和解决实际问题中的数据组织和处理问题。数据结构可以分为线性结构和非线性结构。线性结构包括数组、链表、堆栈和队列等,而非线性结构包括树和图等。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1298

2023.08.09

c语言random函数用法
c语言random函数用法

c语言random函数用法:1、random.random,随机生成(0,1)之间的浮点数;2、random.randint,随机生成在范围之内的整数,两个参数分别表示上限和下限;3、random.randrange,在指定范围内,按指定基数递增的集合中获得一个随机数;4、random.choice,从序列中随机抽选一个数;5、random.shuffle,随机排序。

1416

2023.09.05

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

2318

2023.09.20

c语言get函数的用法
c语言get函数的用法

get函数是一个用于从输入流中获取字符的函数。可以从键盘、文件或其他输入设备中读取字符,并将其存储在指定的变量中。本文介绍了get函数的用法以及一些相关的注意事项。希望这篇文章能够帮助你更好地理解和使用get函数 。

3800

2023.09.20

c数组初始化的方法
c数组初始化的方法

c语言数组初始化的方法有直接赋值法、不完全初始化法、省略数组长度法和二维数组初始化法。详细介绍:1、直接赋值法,这种方法可以直接将数组的值进行初始化;2、不完全初始化法,。这种方法可以在一定程度上节省内存空间;3、省略数组长度法,这种方法可以让编译器自动计算数组的长度;4、二维数组初始化法等等。

17815

2023.09.22

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

60

2026.10.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn