使用 strace 命令了解 Linux 系统调用使用 strace 命令了解 Linux 系统调用使用 strace 命令了解 Linux 系统调用使用 strace 命令了解 Linux 系统调用
  • 业务
  • 目标
  • 支持
  • 登录
找到的结果: {phrase} (显示: {results_count} 共: {results_count_total})
显示: {results_count} 共: {results_count_total}

加载更多搜索结果...

搜索范围
模糊匹配
搜索标题
搜索内容

使用 strace 命令了解 Linux 系统调用

发表 admin at 2025年2月28日
类别
  • 未分类
标签
コアサーバーV2プランご契約でドメイン更新費用が永久無料

桌面上运行的每个进程都使用系统调用与操作系统进行通信。使用 strace,您可以轻松跟踪此类系统调用。

当Linux上运行的程序想要使用操作系统管理的资源(读取文件、创建进程等)时,它们会对操作系统进行系统调用。系统调用在内核级别工作并执行必要的操作,将控制权交还给调用程序。 strace 工具提供了在 Linux 上跟踪这些系统调用的能力。

strace 命令的典型用法

要监视应用程序的系统调用,只需按以下格式使用 strace 调用命令:

strace ls /tmp

然而,通常有些进程会更早启动并继续在后台运行。由于出现任何问题,您可能需要收集与此类进程相关的其他信息。您可以通过将进程的进程 ID 赋予 -p 参数,将 strace 附加到任何正在运行的应用程序:

strace -p 2759

输出:

跟踪应用程序的线程和分叉

通过 strace,您可以使用 -f 标志检查作为应用程序分支的所有线程和其他子进程。

strace -f -p 2759

输出:

使用 strace 检查某些系统调用

默认的 strace 输出有时会非常拥挤。如果您只想跟踪某些系统调用,可以使用 -e 参数来实现:

strace -f -e trace=open,write,close,connect,select -p 19770

要仅跟踪与文件操作相关的系统调用,请使用-e trace=file:

strace -e trace=file -p 19770

要仅过滤与网络相关的系统调用,请在命令中指定-e trace=network:

strace -e trace=network -p 19770

获取以秒为单位的时间信息

输出系统调用时,可以使用-t参数来获取精确到秒的时间信息。大多数时候,精度不足以满足您的需求。在这种情况下,您可以使用 -tt 参数来获取微秒精度的时间信息:

strace -tt ls /tmp

收集有关系统调用的统计信息

使用-c参数,您可以根据需要收集有关系统调用的统计信息:

strace -f -c -p 19770

将日志保存到文件

如果您运行 strace 很长时间并且想要稍后更详细地检查生成的日志,则需要保存日志。使用 -o 参数,您可以指定 strace 应在其中保存日志的文件:

strace -f -o /tmp/strace.log -e trace=file ls /tmp

ptrace 阻塞过程

使用 prctl 系统调用,Linux 下的任何应用程序都可以使用 ptrace 防止自身被非 root 用户控制。如果应用程序通过 prctl 清除自身的 PR_SET_DUMPABLE 标志,则除 root 之外的用户将无法使用 ptrace 控制该应用程序,即使他们有权向应用程序发出信号。

此功能最典型的用途之一是 OpenSSH 身份验证代理软件。因此,在用户认证时可以防止另一个应用程序通过ptrace控制该应用程序。

跟踪和安全

由于传统 Linux 进程模型中设置的 ptrace 设施,您的用户在系统上运行的任何软件都有权向其中插入恶意代码。从最简单的 xterm 工具到高级 Web 浏览器应用程序,此类恶意软件可以通过 ptrace 系统调用控制所有其他正在运行的应用程序,并在您不注意的情况下复制重要信息。

针对这种很多用户都没有意识到的情况,Linux内核中开发了一种名为Yama的安全模块的保护机制。

您可以通过 /proc/sys/kernel/yama/ptrace_scope 文件控制对 ptrace 系统调用的响应。默认情况下,该文件写入值 0。

以下值是可接受的:

Value

Meaning

Conventional behavior: All applications that have the right to ptrace can be checked.

1

Restricted ptrace: Only the direct parent of the application or debug applications allowed by the application with the PR_SET_PTRACER option have the control. Thus, the uses of gdb program_name and strace program_name will continue to work, but you won't be able to attach a running application afterward.

2

Ptrace to the system administrator: Only applications with defined CAP_SYS_PTRACE property or child processes that define the PTRACE_TRACEME option with prctl can be controlled.

3

Completely disabled: No ptrace is allowed under any circumstances. If this property is defined once, you can't change it again at runtime.

许多开发人员不知道应用程序可以通过 prctl 自行禁用 ptrace,root 用户除外。尽管与安全相关的软件(例如 OpenSSH 代理)执行这些操作,但期望系统上运行的所有软件都具有相同的行为是不正确的。

最近,一些 Linux 发行版已开始将如上所述的 ptrace_scope 文件的默认值设置为 1。因此,通过限制 ptrace 操作,可以为整个系统提供更安全的工作环境。

使用示例 strace

使用名称 ministrace.c 注册下面的示例应用程序。然后你可以使用以下命令编译它:

gcc -o ministrace ministrace.c

代码 :

#include <sys/ptrace.h>
#include <sys/reg.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h> 
int wait_for_syscall (pid_t child)
 {
 int status;
 while (1) {
 ptrace(PTRACE_SYSCALL, child, 0, 0);
 waitpid(child, &status, 0);
 if (WIFSTOPPED(status) && WSTOPSIG(status) & 0x80)
 return 0;
 if (WIFEXITED(status))
 return 1;
 }
 }
 
int do_child (int argc, char **argv)
 {
 char *args [argc+1];
 memcpy(args, argv, argc * sizeof(char*));
 args[argc] = NULL;
 ptrace(PTRACE_TRACEME);
 kill(getpid(), SIGSTOP);
 return execvp(args[0], args);
 }
 
int do_trace (pid_t child)
 {
 int status, syscall, retval;
 waitpid(child, &status, 0);
 ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACESYSGOOD);
 while(1) {
 if (wait_for_syscall(child) != 0) break;
 
 syscall = ptrace(PTRACE_PEEKUSER, child, sizeof(long)*ORIG_RAX);
 fprintf(stderr, "syscall(%d) = ", syscall);
 
 if (wait_for_syscall(child) != 0) break;
 
 retval = ptrace(PTRACE_PEEKUSER, child, sizeof(long)*RAX);
 fprintf(stderr, "%d\n", retval);
 }
 return 0;
 }
int main (int argc, char **argv)
 {
 if (argc < 2) {
 fprintf(stderr, "Usage: %s prog args\n", argv[0]);
 exit(1);
 }
 pid_t child = fork();
 if (child == 0) {
 return do_child(argc-1, argv+1);
 } else {
 return do_trace(child);
 }
 }

编译应用程序后,您可以使用 ministrace 运行任何命令并检查输出:

您可以将 strace 用于多种用途

strace 可以帮助查找程序中不必要地使用系统资源的错误。同样,程序在使用操作系统资源时表现出的特征也可以通过 strace 来揭示。

由于 strace 直接监听系统调用,因此无论正在运行的程序的代码是否打开/关闭,它都可以揭示运行时动态。可以了解为什么程序在开始使用 strace 时会抛出错误。

同样,strace 可以帮助您了解程序意外终止的原因。因此,熟悉strace对于Linux内核开发和系统管理非常重要。

©2015-2025 Norria support@alaica.com