【问题标题】:Why do these instruction counts of ls differ so much? (ptrace vs perf vs qemu)为什么 ls 的这些指令计数差异如此之大? (ptrace vs perf vs qemu)
【发布时间】:2021-02-25 18:40:56
【问题描述】:

我想统计运行 /bin/ls 时执行的指令总数。 我使用了 3 种结果差异很大的方法,但我不知道为什么。

1.使用 ptrace 进行指令计数

我编写了一段代码,它调用 ls 的一个实例并使用 ptrace 单步执行:

#include <stdio.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/user.h>
#include <sys/reg.h>    
#include <sys/syscall.h>

int main()
{   
    pid_t child;
    child = fork(); //create child
    
    if(child == 0) {
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        char* child_argv[] = {"/bin/ls", NULL};
        execv("/bin/ls", child_argv);
    }
    else {
        int status;
        long long ins_count = 0;
        while(1)
        {
            //stop tracing if child terminated successfully
            wait(&status);
            if(WIFEXITED(status))
                break;

                ins_count++;
                ptrace(PTRACE_SINGLESTEP, child, NULL, NULL);
        }

    printf("\n%lld Instructions executed.\n", ins_count);

    }
    
    return 0;
}

运行这段代码会给我 516.678 条指令。

2。 QEMU 单步执行

我在单步模式下使用 qemu 模拟了 ls,并使用以下命令将所有传入指令记录到日志文件中: qemu-x86_64 -singlestep -D 日志文件 -d in_asm /bin/ls

根据qemuls执行16.836条指令。

3.性能

sudo perf stat ls

这个命令让我执行了 8.162.180 条指令。

我知道这些指令中的大多数来自动态链接器,它们可以被计算在内。但为什么这些数字相差如此之大?他们不应该都一样吗?

【问题讨论】:

  • 你自己的程序会统计ld-linux.so的指令,但不统计系统调用的指令(syscall算作一条指令)。我猜(我不知道)perf 会计算 Linux 内核中的指令(所以一个 syscall 是数千条指令)而“qemu”不计算 ld-linux.so
  • 谢谢!所以如果我的代码跳过“ld-linux.so”的指令,我应该得到与 qemu 相同的计数?

标签: c linux qemu perf ptrace


【解决方案1】:

为什么这些指令计数差异如此之大?因为他们真正衡量的东西不同,只有衡量的单位是一样的。就好像你在称你从商店里拿来的东西,一个人称所有的东西都没有包装,甚至没有贴纸,另一个人称它在包装中,也包括购物袋,还有一个人还加了你带来的泥土。房子在你的靴子上。

这几乎就是这里发生的事情:指令计数不仅仅是 ls 二进制文件中的指令计数,还可以包括它使用的库,内核加载器的服务需要引入这些库,最后是在进程中但在内核上下文中执行的代码。在这方面,您使用的方法都表现不同。所以问题是:你需要从那个测量中得到什么?如果你需要“总的努力”,那么最大的肯定就是你想要的:这将包括内核造成的一些开销。如果你需要“我只想知道ls发生了什么”,那么最小的数字就是你想要的。

【讨论】:

  • 我的目标是通过与 qemu 相同的指令进行交互。 Qemu 可以在迭代程序指令时转储寄存器,我想对我的 ptrace 代码做同样的事情,迭代与 qemu 相同的指令并转储寄存器以进行比较,不幸的是,qemu 的文档不多,我不是通过查看 qemu 源码有足够的经验来理解它。
  • 那你就得用qemu了。时期。您将无法使用 ptrace 做到这一点 - 为什么您认为可以?这是不可能的。 qemu 可以一直模拟到虚拟机级别,即它模拟整个 PC,并将模拟内核,因此它对所有执行级别都有“洞察力”。它可用于仅进行部分仿真,例如要在 Intel CPU 上运行 ARM linux 代码,但必须以这种方式进行设置,而且您对精确设置一无所知。 ptrace 不会追踪到内核代码,就是这样。
  • QEMU 部分的具体答案是“'in_asm' 日志根本不是总执行指令的计数!” -- 请参阅我对*.com/questions/64847254/…的回答中的详细说明