如何使用ftrace跟踪系统调用事件而不显示Linux内核中的任何其他函数?

例如,要监控所有mkdir调用,我能想到的最好的是:

#!/bin/sh
set -eux

d=debug/tracing

mkdir -p debug
if ! mountpoint -q debug; then
  mount -t debugfs nodev debug
fi

# Stop tracing.
echo 0 > "${d}/tracing_on"

# Clear previous traces.
echo > "${d}/trace"

# Enable tracing mkdir
echo sys_enter_mkdir > "${d}/set_event"

# Set tracer type.
echo function > "${d}/current_tracer"

# Filter only sys_mkdir as a workaround.
echo SyS_mkdir > "${d}/set_ftrace_filter"

# Start tracing.
echo 1 > "${d}/tracing_on"

# Generate two mkdir calls.
rm -rf /tmp/a
rm -rf /tmp/b
mkdir /tmp/a
mkdir /tmp/b

# View the trace.
cat "${d}/trace"

# Stop tracing.
echo 0 > "${d}/tracing_on"

umount debug

然后在运行sudo后,它给出:

# tracer: function
#
# entries-in-buffer/entries-written: 4/4   #P:16
#
#                              _-----=> irqs-off
#                             / _----=> need-resched
#                            | / _---=> hardirq/softirq
#                            || / _--=> preempt-depth
#                            ||| /     delay
#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
#              | |       |   ||||       |         |
           mkdir-31254 [015] .... 2010985.576760: sys_mkdir(pathname: 7ffc54b32c77, mode: 1ff)
           mkdir-31254 [015] .... 2010985.576763: SyS_mkdir <-tracesys_phase2
           mkdir-31255 [007] .... 2010985.578363: sys_mkdir(pathname: 7fff02d90c77, mode: 1ff)
           mkdir-31255 [007] .... 2010985.578365: SyS_mkdir <-tracesys_phase2

我的问题是它为每个系统调出输出两行:

> sys_mkdir这是我想要的事件
> SyS_mkdir是过滤后的函数解决方法,我不想看到它

如果我改为尝试:

echo > "${d}/set_ftrace_filter"

或者根本不接触该文件,然后它显示了大量的功能,并且很难对系统调用进行打算.

如果有更好的方法来禁用常规功能,并保持只是系统调用事件?

我可以使用SyS_mkdir并禁用我猜的syscall事件,但如果我可以使用更具体的事件感觉更干净?也:

>事件显示的参数更好.
> syscall函数名称在内核版本中发生更改.例如,在Linux v4.18上它已经是__x64_sys_mkdir而不是SyS_mkdir.

有关:

> How to trace the write system call in the Linux kernel?

测试了Ubuntu 18.04,Linux内核4.15.

解决方法:

此外,值得一提的是获得此类信息的另一种简洁方法.人们可以这样做:

stap -e 'probe syscall.mkdir { printf("%s[%d] -> %s(%s)\n", execname(), pid(), name, argstr) }'

输出:

systemd-journal[318] -> mkdir("/var/log/journal/c8d2562a041649cdbfd1ac5e24dbe0db", 0755)
systemd-journal[318] -> mkdir("/var/log/journal/c8d2562a041649cdbfd1ac5e24dbe0db", 0755)
mkdir[4870] -> mkdir("wtf", 0777)
...

其他方式:

stap -e 'probe kernel.function("sys_mkdir") { printf("%s[%d] (%s)\n", execname(), pid(), $$parms) }'

输出:

systemd-journal[318] (pathname=0x55b74f7ab8b0 mode=0x1ed)
systemd-journal[318] (pathname=0x55b74f7ab8b0 mode=0x1ed)
mkdir[8532] (pathname=0x7ffcf30af761 mode=0x1ff)
...

您可以根据需要自定义输出.

附: Systemtap基于kprobes. Architecture doc将有助于了解其内部结构.

More about the SystemTap.

上一篇:vue学习笔记 六、ref定义单个数据


下一篇:如何从Linux中的ftrace中的特定函数开始获取完整的调用图?