如何在Linux中跟踪系统调用?

如何在Linux中跟踪系统调用?,linux,kernel,system-calls,Linux,Kernel,System Calls,如何跟踪从陷阱到内核的系统调用、参数的传递方式、系统调用在内核中的位置、系统调用在内核中的实际处理、返回给用户以及状态如何恢复?您可以使用-f和-ff选项。大概是这样的: strace -f -e trace=process bash -c 'ls; :' -f跟踪当前跟踪的子进程所创建的子进程 作为一个整体的过程 fork(2)系统调用的结果 -ff如果-o filename选项有效,则每个进程跟踪都会写入 filename.pid,其中pid是每个进程的数字进程id。这是 与-c不兼容,因

如何跟踪从陷阱到内核的系统调用、参数的传递方式、系统调用在内核中的位置、系统调用在内核中的实际处理、返回给用户以及状态如何恢复?

您可以使用-f和-ff选项。大概是这样的:

strace -f -e trace=process bash -c 'ls; :'
-f跟踪当前跟踪的子进程所创建的子进程 作为一个整体的过程 fork(2)系统调用的结果

-ff如果-o filename选项有效,则每个进程跟踪都会写入 filename.pid,其中pid是每个进程的数字进程id。这是 与-c不兼容,因为不保留每个进程的计数


它实际上相对容易使用
ftrace
。这是作者的一篇经典文章。第二部分是研究


Linux基础的J.J. Simon M·奥勒,还有许多其他好的入门文章,你可以用“F追踪教程”或“fTraceTrimes”等搜索术语找到。

< P> <强> StaseTab<强> < /P> 这是迄今为止我发现的最有效的方法。它甚至可以显示调用参数:

用法:

sudo apt-get install systemtap
sudo stap -e 'probe syscall.mkdir { printf("%s[%d] -> %s(%s)\n", execname(), pid(), name, argstr) }'
然后在另一个终端上:

sudo rm -rf /tmp/a /tmp/b
mkdir /tmp/a
mkdir /tmp/b
样本输出:

mkdir[4590] -> mkdir("/tmp/a", 0777)
mkdir[4593] -> mkdir("/tmp/b", 0777)
# tracer: nop
#
#                              _-----=> irqs-offhttps://sourceware.org/systemtap/documentation.html
#                             / _----=> need-resched
#                            | / _---=> hardirq/softirq
#                            || / _--=> preempt-depth
#                            ||| /     delay
#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
#              | |       |   ||||       |         |
           mkdir-5619  [005] .... 10249.262531: sys_mkdir(pathname: 7fff93cbfcb0, mode: 1ff)
           mkdir-5620  [003] .... 10249.264613: sys_mkdir(pathname: 7ffcdc91ecb0, mode: 1ff)
文件:

似乎是基于kprobes的:

另见:

在Ubuntu 18.04、Linux内核4.15上测试

ltrace-S
同时显示系统调用和库调用

因此,这个很棒的工具可以进一步了解可执行文件的工作

举个例子,我用它来分析系统调用
dlopen
正在做什么:

ftrace
最小可运行示例

在中提到,但这里有一个最小的可运行示例

使用
sudo运行

#!/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"

# Find the tracer name.
cat "${d}/available_tracers"

# Disable tracing functions, show only system call events.
echo nop > "${d}/current_tracer"

# Find the event name with.
grep mkdir "${d}/available_events"

# Enable tracing mkdir.
# Both statements below seem to do the exact same thing,
# just with different interfaces.
# https://www.kernel.org/doc/html/v4.18/trace/events.html
echo sys_enter_mkdir > "${d}/set_event"
# echo 1 > "${d}/events/syscalls/sys_enter_mkdir/enable"

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

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

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

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

umount debug
样本输出:

mkdir[4590] -> mkdir("/tmp/a", 0777)
mkdir[4593] -> mkdir("/tmp/b", 0777)
# tracer: nop
#
#                              _-----=> irqs-offhttps://sourceware.org/systemtap/documentation.html
#                             / _----=> need-resched
#                            | / _---=> hardirq/softirq
#                            || / _--=> preempt-depth
#                            ||| /     delay
#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
#              | |       |   ||||       |         |
           mkdir-5619  [005] .... 10249.262531: sys_mkdir(pathname: 7fff93cbfcb0, mode: 1ff)
           mkdir-5620  [003] .... 10249.264613: sys_mkdir(pathname: 7ffcdc91ecb0, mode: 1ff)
这种方法的一个很酷的地方是,它一次显示系统上所有进程的函数调用,尽管您也可以使用
set\ftrace\u pid
过滤感兴趣的pid

文件位于:

在Ubuntu 18.04、Linux内核4.15上测试

GDB步骤调试Linux内核

根据您需要的内部细节级别,这是一个选项:

strace
最小可运行示例

下面是一个最小的可运行的
strace
:有一个独立的hello-world,它使一切工作都非常清楚

更多信息

  • 可能值得一读,它提到:

    perf top -F 49 -e raw_syscalls:sys_enter --sort comm,dso --show-nr-samples
    
    以及基于BPF的traceloop:文章声称这是一种非常快速的方法:

    sudo -E ./traceloop cgroups --dump-on-exit /sys/fs/cgroup/system.slice/sshd.service
    
注意:“进程”是指内核对进程的概念,在userland中通常称为“线程”。