在被分析的程序(或控制进程)和 perf 进程之间有一种进程间通信机制可以实现此目的:使用--control
格式中的选项--control=fifo:ctl-fifo[,ack-fifo]
或--control=fd:ctl-fd[,ack-fd]
如perf-stat(1)联机帮助页中讨论的那样。该选项指定一对 FIFO 文件(命名管道)的路径名或一对文件描述符。第一个文件用于发出命令以启用或禁用正在侦听同一文件的任何 perf 进程中的所有事件。第二个文件是可选的,用于检查 perf 何时实际执行了命令。
手册页中有一个示例,展示了如何使用此选项从 bash 脚本控制 perf 进程,您可以轻松地将其转换为 C/C++:
ctl_dir=/tmp/
ctl_fifo=${ctl_dir}perf_ctl.fifo
test -p ${ctl_fifo} && unlink ${ctl_fifo}
mkfifo ${ctl_fifo}
exec ${ctl_fd}<>${ctl_fifo} # open for read+write as specified FD
Run Code Online (Sandbox Code Playgroud)
首先检查文件/tmp/perf_ctl.fifo
(如果存在)是否是命名管道,然后才将其删除。如果文件不存在,这不是问题,但如果它存在并且不是命名管道,则不应删除该文件,而mkfifo
应该失败。创建mkfifo
一个名为 pathname 的命名管道/tmp/perf_ctl.fifo
。然后,下一个命令以读/写权限打开文件,并将文件描述符分配给ctl_fd
. 等效的系统调用是fstat
、unlink
、mkfifo
和open
。请注意,命名管道将由 shell 脚本(控制进程)或正在分析的进程写入,并从 perf 进程中读取。对第二个命名管道重复相同的命令,ctl_fd_ack
该管道将用于接收来自 perf 的确认。
perf stat -D -1 -e cpu-cycles -a -I 1000 \
--control fd:${ctl_fd},${ctl_fd_ack} \
-- sleep 30 &
perf_pid=$!
Run Code Online (Sandbox Code Playgroud)
这会分叉当前进程并perf stat
在子进程中运行程序,子进程继承相同的文件描述符。该-D -1
选项告诉 perf 在禁用所有事件的情况下启动。您可能需要按如下方式更改 perf 选项:
perf stat -D -1 -e <your event list> --control fd:${ctl_fd},${ctl_fd_ack} -p pid
Run Code Online (Sandbox Code Playgroud)
在这种情况下,要分析的程序与控制进程相同,因此告诉 perf 使用 来分析已经运行的程序-p
。子进程中紧随其后的是等效的系统fork
调用。execv
sleep 5 && echo 'enable' >&${ctl_fd} && read -u ${ctl_fd_ack} e1 && echo "enabled(${e1})"
sleep 10 && echo 'disable' >&${ctl_fd} && read -u ${ctl_fd_ack} d1 && echo "disabled(${d1})"
Run Code Online (Sandbox Code Playgroud)
示例脚本休眠约 5 秒,将“enable”写入管道ctl_fd
,然后检查 perf 的响应以确保事件已启用,然后在约 10 秒后继续禁用事件。等效的系统调用是write
和read
。
脚本的其余部分删除文件描述符和管道文件。
现在把它们放在一起,您的程序应该如下所示:
/* PART 1
Initialization code.
*/
/* PART 2
Create named pipes and fds.
Fork perf with disabled events.
perf is running now but nothing is being measured.
You can redirect perf output to a file if you wish.
*/
/* PART 3
Enable events.
*/
/* PART 4
The code you want to profile goes here.
*/
/* PART 5
Disable events.
perf is still running but nothing is being measured.
*/
/* PART 6
Cleanup.
Let this process terminate, which would cause the perf process to terminate as well.
Alternatively, use `kill(pid, SIGINT)` to gracefully kill perf.
perf stat outputs the results when it terminates.
*/
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1398 次 |
最近记录: |