Я хочу подсчитать общее количество инструкций, выполненных при запуске /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
Я смоделировал ls, используя qemu в пошаговом режиме, и записал все входящие инструкции в файл журнала с помощью следующей команды: qemu-x86_64 -singlestep -D logfile -d in_asm /bin/ls
По данным qemul ls выполняет 16 836 инструкций.
<сильный>3. производительность
sudo perf stat ls
Эта команда дала мне 8.162.180 выполненных инструкций.
Я знаю, что большинство этих инструкций исходит от динамического компоновщика, и это нормально, что они учитываются. Но почему эти цифры так сильно различаются? Разве они не должны быть одинаковыми?
ld-linux.so
, но не инструкции системных вызовов (syscall
считается как одна инструкция). Я предполагаю (я не знаю), чтоperf
будет считать инструкции в ядре Linux (поэтому однаsyscall
- это тысячи инструкций), а qemu не считаетld-linux.so
. - person Martin Rosenau   schedule 13.11.2020