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

如何在Linux下检测程序是否被perf分析,按需输出JIT符号?

检测程序是否被perf分析的几种实用方法

针对你需要仅在被perf分析时输出JIT符号的需求,下面是几个Linux下编程式检测的可行方案:

1. 检查/proc/self/status的TracerPid字段

Linux的/proc文件系统会记录进程的追踪状态,/proc/self/status里的TracerPid字段如果非0,说明当前进程被另一个进程追踪。我们可以进一步检查追踪进程的命令行是否包含"perf":

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int is_traced_by_perf() {
    FILE *fp = fopen("/proc/self/status", "r");
    if (!fp) return 0;

    char line[256];
    pid_t tracer_pid = 0;
    while (fgets(line, sizeof(line), fp)) {
        if (strncmp(line, "TracerPid:", 10) == 0) {
            sscanf(line + 10, "%d", &tracer_pid);
            break;
        }
    }
    fclose(fp);

    if (tracer_pid == 0) return 0;

    char cmd_path[64];
    snprintf(cmd_path, sizeof(cmd_path), "/proc/%d/cmdline", tracer_pid);
    fp = fopen(cmd_path, "r");
    if (!fp) return 0;

    char cmd[256];
    fgets(cmd, sizeof(cmd), fp);
    fclose(fp);

    return strstr(cmd, "perf") != NULL;
}

注意:如果perf被重命名或通过别名调用,这个方法可能失效,适合大多数常规场景。

2. 遍历进程FD检查perf_event文件

perf分析时会为目标进程打开perf_event类型的文件描述符,我们可以遍历/proc/self/fd目录,检查是否存在指向这类文件的链接:

#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int has_perf_events() {
    DIR *dir = opendir("/proc/self/fd");
    if (!dir) return 0;

    struct dirent *entry;
    int found = 0;
    char link_path[64], target[256];

    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_type != DT_LNK) continue;
        snprintf(link_path, sizeof(link_path), "/proc/self/fd/%s", entry->d_name);
        ssize_t len = readlink(link_path, target, sizeof(target)-1);
        if (len == -1) continue;
        target[len] = '\0';
        if (strstr(target, "/perf_event") != NULL) {
            found = 1;
            break;
        }
    }
    closedir(dir);
    return found;
}

这个方法更可靠,不管perf进程名是什么,只要有perf事件附着就能检测到,性能开销可以忽略。

3. 捕获perf默认发送的SIGUSR1信号

perf默认会在附加到进程时发送SIGUSR1信号,你可以通过捕获这个信号来触发JIT符号输出,无需主动检测:

#include <signal.h>
#include <stdio.h>

static int perf_attached = 0;

void perf_signal_handler(int sig) {
    perf_attached = 1;
    // 在这里执行JIT符号输出逻辑
}

int main() {
    signal(SIGUSR1, perf_signal_handler);
    // 主程序逻辑...

    if (perf_attached) {
        // 输出JIT符号
    }
    return 0;
}

注意:用户可以通过perf record -s <信号>修改触发信号,如果需要兼容这种情况,可以结合前面的检测方法做兜底。

方案选择建议

  • 追求准确性:优先用检查perf_event FD的方法。
  • 追求高效被动触发:用捕获SIGUSR1的方法。
  • 简单场景:用TracerPid检查作为快速方案,但要注意排除gdb等其他追踪工具的干扰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 04:18:19