如何使用 strace 监控 Linux 系统调用

已发表: 2022-01-29
笔记本电脑上的程式化终端窗口。
fatmawati achmad zaenuri/Shutterstock.com

Linux 程序要求内核为它们做一些事情。 strace命令显示这些系统调用。 您可以使用它们来了解程序如何工作以及为什么有时它们不工作。

内核和系统调用

尽管计算机程序可能很聪明,但它们不能为自己做所有事情。 他们需要请求为他们执行某些功能。 这些请求发送到 Linux 内核。 通常,程序调用一个库或其他软件接口,然后该库向内核发出适当的请求(称为系统调用)。

能够查看程序进行的系统调用以及响应是什么可以帮助您了解您感兴趣或您编写的程序的内部工作原理。 这就是strace的作用。 它可以帮助解决问题并寻找瓶颈。

这与使用gdb之类的工具调试应用程序不同。 调试程序可让您调查程序运行时的内部操作。 它使您可以逐步执行程序的逻辑并检查内存和变量值。 相比之下, strace所做的是在程序运行时捕获系统调用信息。 当被跟踪的程序终止时, strace将系统调用信息列出到终端窗口。

系统调用提供各种低级功能,例如对文件的读写操作、终止进程等。 syscalls 手册页上有数百个系统调用的列表。

相关:使用 GDB 调试:入门

安装 strace

如果您的计算机上尚未安装strace ,您可以非常轻松地安装它。

在 Ubuntu 上,使用以下命令:

 sudo apt install strace 

在 Fedora 上,键入以下命令:

 须藤 dnf 安装 strace 

在 Manjaro 上,命令是:

 sudo pacman -Sy strace 

使用 strace 的第一步

我们将使用一个小程序来演示strace 。 它没有做太多:它打开一个文件并向其中写入一行文本,并且它没有任何错误检查。 这只是一个快速破解,以便我们可以使用strace

 #include <stdio.h>

int main(int argc, char argv[]) { 

  // 文件句柄 
  文件 *fileGeek;

  // 打开一个名为“strace_demo.txt”的文件,或者创建它 
  fileGeek = fopen("strace_demo.txt", "w");

  // 将一些文本写入文件 
  fprintf(fileGeek, "将其写入文件" );

  //关闭文件 
  fclose(文件极客);

  // 退出程序 
  返回(0); 

} // main 结束

我们将它保存到一个名为“file- io.c ”的文件中,并使用gcc将其编译为一个名为stex的可执行文件,以“ st race example”命名。

 gcc -o stex 文件-io.c

我们将从命令行调用strace并将新可执行文件的名称作为我们想要跟踪的进程传递给它。 我们可以轻松地跟踪任何 Linux 命令或任何其他二进制可执行文件。 我们使用我们的小程序有两个原因。

第一个原因是strace很冗长。 可以有很多输出。 当你在愤怒中使用strace时这很好,但一开始它可能会让人不知所措。 我们的小程序的strace输出有限。 第二个原因是我们的程序功能有限,源代码简短明了。 这使得更容易识别输出的哪些部分引用了程序内部工作的不同部分。

 strace ./stex 

我们可以清楚地看到write系统调用将文本“Write this to the file”发送到我们打开的文件和exit_group系统调用。 这将终止应用程序中的所有线程并将返回值发送回 shell。

过滤输出

即使使用我们简单的演示程序,也有相当多的输出。 我们可以使用-e (表达式)选项。 我们将传入我们想要查看的系统调用的名称。

 strace -e 写./stex 

广告

您可以通过将它们添加为逗号分隔的列表来报告多个系统调用。 不要在系统调用列表中包含任何空格。

 strace -e 关闭,写入 ./stex 

将输出发送到文件

过滤输出的好处也是过滤输出的问题。 你看到了你要求看到的东西,但你看不到其他任何东西。 并且其他一些输出可能对您来说比您要求查看的内容更有用。

有时,捕获所有内容并搜索和滚动整个结果集会更方便。 这样,您就不会意外排除任何重要的内容。 -o (输出)选项允许您将strace会话的输出发送到文本文件。

 strace -o 跟踪输出.txt ./stex 

然后,您可以使用less命令滚动列表并按名称搜索系统调用或其他任何内容。

 更少的trace-output.txt 

您现在可以使用所有less的搜索功能来调查输出。

相关:如何在 Linux 上使用 less 命令

添加时间戳

您可以在输出中添加几个不同的时间戳。 -r (相对时间戳)选项添加时间戳,显示每个连续系统调用开始之间的时间差。 请注意,这些时间值将包括上一次系统调用所花费的时间以及程序在下一次系统调用之前所做的任何其他事情。

 strace -r ./stex 

广告

时间戳显示在每行输出的开头。

要查看每个系统调用所花费的时间,请使用-T (系统调用时间)选项。 这显示了在每个系统调用中花费的持续时间。

 strace -T ./stex 

持续时间显示在每个系统调用行的末尾。

要查看调用每个系统调用的时间,请使用-tt (绝对时间戳)选项。 这显示了“挂钟”时间,分辨率为微秒。

 strace -tt ./stex 

时间显示在每行的开头。

跟踪正在运行的进程

如果您要跟踪的进程已经在运行,您仍然可以将strace附加到它。 为此,您需要知道进程 ID。 您可以使用psgrep来找到它。 我们正在运行 Firefox。 要找出firefox进程的 ID,我们可以使用ps并通过grep管道它。

 ps -e | grep 火狐

广告

我们可以看到进程 ID 是 8483。我们将使用-p (进程 ID)选项告诉strace附加到哪个进程。 请注意,您需要使用sudo

 须藤 strace -p 8483 

您将看到一条通知,表明strace已将自身附加到进程,然后系统跟踪调用将照常显示在终端窗口中。

创建报告

-c (仅限摘要)选项使strace打印报告。 它会生成一个表,以获取有关被跟踪程序进行的系统调用的信息。

 strace -c ./stex 

这些列是:

  • % time :每个系统调用所花费的执行时间的百分比。
  • seconds :每个系统调用所花费的总时间,以秒和微秒表示。
  • usecs/call :每个系统调用花费的平均时间(以微秒为单位)。
  • call :每个系统调用被执行的次数。
  • errors :每个系统调用的失败次数。
  • syscall :系统调用的名称。

对于快速执行和终止的琐碎程序,这些值将显示为零。 实际值显示为比我们的演示应用程序更有意义的程序。

深入洞察,轻松

strace输出可以显示正在执行哪些系统调用,正在重复执行哪些系统调用,以及在内核端代码中花费了多少执行时间。 这是很好的信息。 通常,当您试图了解代码内部发生的事情时,很容易忘记您的二进制文件几乎不间断地与内核交互以执行其许多功能。

通过使用strace ,您可以看到完整的画面。

相关:适合开发人员和爱好者的最佳 Linux 笔记本电脑