通过 child 分析一个进程,然后杀死 child
Profile a process via its child and kill the child afterwards
我正在尝试找出一种方法来通过 child 在 C 中分析一个进程,片刻之后 parent 进程终止了它的 child 停止分析。我正在使用 perf 来分析我的应用程序。 perf 将在被终止时将其结果输出到一个文件中。在 bash 脚本中看起来像这样:
./run &
perf stat -o perf.data -p <pid_run> &
kill -9 <pid_perf>
到目前为止我做了什么:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
static pid_t perf_id;
void start() {
char *filename="test_data";
char ppid_str[24];
pid_t pid = fork();
if (pid == 0){
pid_t ppid = getppid();
sprintf(ppid_str, "%d",ppid);
char *args[] = {"/usr/bin/perf", "stat","-p",ppid_str,"-o", filename, NULL};
execvp(args[0], args);
}
else {
perf_id = pid
}
}
void stop() {
kill(perf_id,SIGKILL);
}
我在获取 perf 的输出时遇到问题。
这是一个可以 运行 parent 过程的代码示例:
int main() {
start();
int a = 0;
a+=1;
stop();
// ... // There are other instructions after the stop
return 0;
}
当 运行 执行此代码时,我没有从 perf 获得任何输出。我必须终止 parent 进程才能获得输出。
如果我在终止 child 进程之前调用 sleep,那么程序将输出一个空文件。
编辑:
stat 参数是我命令中的一个示例,我还想使用 record 参数
正如 Zulan 所提到的,如果我使用 SIGINT
而不是 SIGKILL
,我将得到一个输出,但只有当主进程休眠 1 秒时我才能得到一个。
问题是 perf 将自身附加到进程,然后等待进程终止以打印计数器。尝试添加例如
-I msec
perf 选项 -I 1000 每 1 秒打印一次计数器。
将您的 args 更改为 execvp 到
char *args[] = {"/usr/bin/perf", "stat", "-p",ppid_str,"-o", filename, "-I", "1000", NULL};
和你的公司进入类似
的循环
while (a < 10) {
a += 1;
sleep(1);
}
虽然在这种方法中文件未正确关闭(),但仍会产生结果。
我会创建一个小的二进制文件来执行 perf 超时并优雅地关闭文件和 运行 来自 child.
的文件
您应该发送 SIGINT
而不是 SIGKILL
以允许 perf
彻底关闭并生成有效的输出文件。 perf
子进程与主进程之间的同步仍然不完善 - 因此如果主进程不像您的示例那样花费大量时间,则很可能根本不会生成任何输出文件。这也会影响收集数据的准确性。通过使用 perf
作为子进程而不是相反的设置,您无法真正改进它。
我正在尝试找出一种方法来通过 child 在 C 中分析一个进程,片刻之后 parent 进程终止了它的 child 停止分析。我正在使用 perf 来分析我的应用程序。 perf 将在被终止时将其结果输出到一个文件中。在 bash 脚本中看起来像这样:
./run &
perf stat -o perf.data -p <pid_run> &
kill -9 <pid_perf>
到目前为止我做了什么:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
static pid_t perf_id;
void start() {
char *filename="test_data";
char ppid_str[24];
pid_t pid = fork();
if (pid == 0){
pid_t ppid = getppid();
sprintf(ppid_str, "%d",ppid);
char *args[] = {"/usr/bin/perf", "stat","-p",ppid_str,"-o", filename, NULL};
execvp(args[0], args);
}
else {
perf_id = pid
}
}
void stop() {
kill(perf_id,SIGKILL);
}
我在获取 perf 的输出时遇到问题。 这是一个可以 运行 parent 过程的代码示例:
int main() {
start();
int a = 0;
a+=1;
stop();
// ... // There are other instructions after the stop
return 0;
}
当 运行 执行此代码时,我没有从 perf 获得任何输出。我必须终止 parent 进程才能获得输出。
如果我在终止 child 进程之前调用 sleep,那么程序将输出一个空文件。
编辑:
stat 参数是我命令中的一个示例,我还想使用 record 参数
正如 Zulan 所提到的,如果我使用 SIGINT
而不是 SIGKILL
,我将得到一个输出,但只有当主进程休眠 1 秒时我才能得到一个。
问题是 perf 将自身附加到进程,然后等待进程终止以打印计数器。尝试添加例如
-I msec
perf 选项 -I 1000 每 1 秒打印一次计数器。 将您的 args 更改为 execvp 到
char *args[] = {"/usr/bin/perf", "stat", "-p",ppid_str,"-o", filename, "-I", "1000", NULL};
和你的公司进入类似
的循环while (a < 10) {
a += 1;
sleep(1);
}
虽然在这种方法中文件未正确关闭(),但仍会产生结果。 我会创建一个小的二进制文件来执行 perf 超时并优雅地关闭文件和 运行 来自 child.
的文件您应该发送 SIGINT
而不是 SIGKILL
以允许 perf
彻底关闭并生成有效的输出文件。 perf
子进程与主进程之间的同步仍然不完善 - 因此如果主进程不像您的示例那样花费大量时间,则很可能根本不会生成任何输出文件。这也会影响收集数据的准确性。通过使用 perf
作为子进程而不是相反的设置,您无法真正改进它。