You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何查询Ubuntu下指定PID进程(如QEMU)的CPUID调用情况

Ubuntu下指定进程/QEMU实例CPUID调用统计实现方案

可按落地成本、场景需求从以下三个方案里选,全部适配原生Ubuntu系统,不需要额外第三方依赖:

方案1:bpftrace轻量动态追踪(生产环境首选,零侵入)

基于内核eBPF能力实现,不需要重启进程、不需要修改QEMU配置,性能损耗低于1%,可以实时统计运行中进程的CPUID调用行为,支持按需启停。
核心逻辑是通过uprobe匹配目标进程用户态的CPUID指令(二进制固定编码为0f a2),同时通过kprobe挂载KVM的CPUID处理函数,同时覆盖QEMU自身调用宿主机CPUID、QEMU处理虚拟机Guest内部CPUID请求两类场景。

  • 先安装依赖:
    sudo apt update && sudo apt install bpftrace linux-tools-common linux-tools-$(uname -r)
    
  • 找到目标QEMU实例的PID:执行pidof qemu-system-x86_64,从返回的进程列表里匹配你要统计的虚拟机实例对应的PID即可
  • 新建追踪脚本cpuid_trace.bt,内容如下:
    #!/usr/bin/env bpftrace
    BEGIN
    {
      printf("追踪启动,目标PID: %d,按Ctrl+C终止并输出统计结果\n", $1);
    }
    
    // 统计QEMU用户态自身触发的CPUID调用
    uprobe:./**/*:
    /pid == $1 && *u8(reg("ip")) == 0x0f && *u8(reg("ip")+1) == 0xa2/
    {
      $leaf = reg("ax");
      $subleaf = reg("cx");
      @host_cpuid_count[$leaf, $subleaf] = count();
    }
    
    // 统计Guest虚拟机触发的CPUID请求
    kprobe:kvm_emulate_cpuid
    /pid == $1/
    {
      $leaf = arg1;
      $subleaf = arg2;
      @guest_cpuid_count[$leaf, $subleaf] = count();
    }
    
    END
    {
      printf("\n=== QEMU进程自身调用宿主机CPUID统计 ===\n");
      printf("%-8s %-8s %-8s\n", "LEAF", "SUBLEAF", "CALL_CNT");
      print(@host_cpuid_count);
    
      printf("\n=== 虚拟机Guest触发CPUID统计 ===\n");
      printf("%-8s %-8s %-8s\n", "LEAF", "SUBLEAF", "CALL_CNT");
      print(@guest_cpuid_count);
    
      clear(@host_cpuid_count); clear(@guest_cpuid_count);
    }
    
  • 加执行权限后运行:sudo chmod +x cpuid_trace.bt && sudo ./cpuid_trace.bt <目标PID>
  • 等虚拟机跑过完整业务负载后按Ctrl+C,就能拿到所有实际触发过的CPUID功能号(leaf)、子功能号(subleaf)和调用次数,对应CPU架构的CPUID编程手册就能匹配到具体功能。

注意:该方案只能统计脚本运行期间的CPUID调用,如果需要覆盖进程从启动开始的全量调用,选下面两个方案。

方案2:perf/ptrace全生命周期追踪

如果需要无遗漏统计进程从启动到退出的所有CPUID调用,有两种落地方式:

  • 快速实现:用perf的Intel PT(处理器追踪)能力,直接采集进程执行流里的所有CPUID指令事件,不需要写代码:
    # 附加到运行中进程采集
    sudo perf record -e intel_pt//u -p <目标PID> --filter 'filter op cpuid'
    # 采集完成后解析结果
    sudo perf script | grep cpuid | awk '{print $9,$10}' | sort | uniq -c
    
    该方式要求CPU支持Intel PT(Intel 5代酷睿以上、AMD Zen2以上都支持),短时间采集性能损耗可接受,长时间采集会生成较大的trace文件。
  • 自定义实现:基于ptrace写轻量追踪器,启动QEMU时就附加,扫描进程所有可执行内存段找到CPUID指令位置,替换为断点指令0xcc,每次触发断点时读取寄存器记录leaf/subleaf,还原指令单步执行后恢复断点;针对QEMU TCG模式动态生成的代码,定期扫描新映射的可执行内存段补断点即可,该方式灵活性最高,可按需定制统计维度。

方案3:QEMU原生埋点统计(虚拟化场景最精准)

如果可以重启QEMU实例,直接用QEMU自带的能力即可,不需要内核态追踪,准确率100%,性能无损耗:

  • 无代码修改方式:启动QEMU时加自带的debug参数,把所有CPUID处理日志输出到指定文件:
    # 在原有QEMU启动参数末尾加这两个参数
    -d cpuid -D /var/log/qemu_cpuid_trace.log
    
    运行一段时间后直接解析日志去重,就能拿到所有Guest触发的CPUID调用记录,完全没有误报。
  • 定制化方式:如果是自行编译的QEMU版本,可以直接在CPUID处理入口(TCG模式对应helper_cpuid函数、KVM模式对应kvm_handle_cpuid函数)加哈希表统计逻辑,还可以扩展QMP命令支持实时查询已调用的CPUID功能列表,适合长期运行的生产环境做常态化统计。

统计时注意区分两类CPUID调用:如果你的目标是明确虚拟机实际用到的虚拟CPUID特性,优先统计Guest触发的CPUID请求即可,QEMU进程自身调用宿主机CPUID一般是初始化硬件适配、特性检测用,和虚拟机业务实际用到的特性无关。

内容的提问来源于stack exchange,提问作者chegov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 07:15:33