我如何跟踪从陷阱到内核的系统调用,如何传递参数,系统调用内核的方式,内核中系统调用的实际处理,返回对用户以及状态如何恢复?
答案 0 :(得分:3)
实际上使用{ 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
相对容易。这是Steven, "Mr. ftrace", Rostedt的经典文章。第二部分是here。
Linux基金会的Jan-SimonMöller有一个free video,还有许多其他好的介绍性文章,您可以使用“ftrace tutorial”或“ftrace example”等搜索词找到。
答案 1 :(得分:3)
SystemTap
这是到目前为止我发现的最强大的方法。它甚至可以显示调用参数:Does ftrace allow capture of system call arguments to the Linux kernel, or only function names?
用法:
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)
文档:https://sourceware.org/systemtap/documentation.html
似乎是基于kprobes的:https://sourceware.org/systemtap/archpaper.pdf
已在Ubuntu 18.04,Linux内核4.15上进行了测试。
ltrace -S
同时显示系统调用和库调用
因此,这个很棒的工具可以进一步了解可执行文件的功能。
例如,在这里我用它来分析系统调用dlopen
在做什么:https://unix.stackexchange.com/questions/226524/what-system-call-is-used-to-load-libraries-in-linux/462710#462710
ftrace
最小可运行示例
在https://stackoverflow.com/a/29840482/895245提及,但这里有一个最小的可运行示例。
运行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
示例输出:
# 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_pid
过滤感兴趣的PID。
文档位于:https://www.kernel.org/doc/html/v4.18/trace/index.html
已在Ubuntu 18.04,Linux内核4.15上进行了测试。
答案 2 :(得分:2)
您可以使用-f和-ff选项。像这样:
strace -f -e trace=process bash -c 'ls; :'
-f 跟踪当前跟踪的子进程 作为一个过程 fork(2)系统调用的结果。
-ff 如果-o filename选项生效,则会写入每个进程跟踪 filename.pid其中pid是每个进程的数字进程ID。这是 与-c不兼容,因为不保留每个进程计数。