Linux下如何记录程序进入/退出用户态、内核态的时间戳?
Linux下监控程序进出用户态/内核态时间戳的实现方法
getrusage只能输出累计的用户态、内核态运行总时长,确实无法满足单切换节点的时间戳采集需求,以下是几种可落地的实现方案:
非侵入式追踪方案(无需修改目标程序代码)
ftrace(内核内置工具)
是Linux官方自带的内核追踪框架,无需额外安装依赖,使用系统调用tracepoint可以直接捕获切换时间点:- 先挂载tracefs:
mount -t tracefs nodev /sys/kernel/tracing - 过滤目标进程:
echo 你的目标进程PID > /sys/kernel/tracing/set_ftrace_pid - 开启系统调用进出追踪:
echo 1 > /sys/kernel/tracing/events/syscalls/enable - 读取trace文件即可得到每一次系统调用(对应用户态进入内核态、内核态返回用户态)的纳秒级时间戳:
cat /sys/kernel/tracing/trace
- 先挂载tracefs:
eBPF追踪(更灵活的现代方案)
基于eBPF的bpftrace工具可以用一行命令快速实现需求,示例命令如下:
该方案开销极低,适合生产环境直接使用。bpftrace -e 'tracepoint:syscalls:sys_enter_* /pid == 目标PID/ { printf("进入内核态 时间戳(纳秒): %llu\n", nsecs); } tracepoint:syscalls:sys_exit_* /pid == 目标PID/ { printf("返回用户态 时间戳(纳秒): %llu\n", nsecs); }'
侵入式方案(需要修改目标程序代码)
- 如果你可以修改目标程序的源码,可以在所有系统调用的前后主动调用高精度计时接口打时间戳,精度最高,开销最小:
- x86平台可以直接用
rdtsc指令读取CPU时间戳计数器 - 跨平台可以用
clock_gettime(CLOCK_MONOTONIC_RAW, &ts)获取纳秒级时间
- x86平台可以直接用
以上方案都可以拿到每一次用户态和内核态切换的独立时间戳,不会出现
getrusage仅输出累计总时长的问题。
内容的提问来源于stack exchange,提问作者ecburx
相关产品推荐
相关产品推荐

