发现工作负载使用的 Linux 内核子系统
作者
- Shuah Khan skhan@linuxfoundation.org
- Shefali Sharma sshefali021@gmail.com
维护者
- Shuah Khan skhan@linuxfoundation.org
要点
- 了解构建和运行工作负载所需的系统资源是重要的。
- 可以使用 Linux 追踪和 strace 来发现工作负载使用的系统资源。系统使用信息的完整性取决于工作负载覆盖的完整性。
- 可以借助工具(如 perf、stress-ng、paxtest)来分析操作系统的性能和安全性。
- 一旦我们发现并了解了工作负载的需求,就可以专注于它们,以避免回归,并用它们来评估安全性考虑。
方法论
strace 是一种诊断、指导和调试工具,可用于发现工作负载使用的系统资源。一旦我们发现并了解了工作负载的需求,就可以专注于它们,以避免回归,并用它们来评估安全性考虑。我们使用 strace 工具来追踪工作负载。
使用 strace 追踪的方法告诉我们工作负载调用的系统调用,并不包括它可能调用的所有系统调用。此外,这种追踪方法只告诉我们调用的系统调用中的代码路径。例如,如果工作负载成功打开文件并从中读取,则追踪的是成功路径。该系统调用中的任何错误路径都不会被追踪。如果有一个工作负载提供了对工作负载的完整覆盖,那么这里概述的方法将追踪并找到所有可能的代码路径。系统使用信息的完整性取决于工作负载覆盖的完整性。
目标是在运行默认内核的系统上追踪工作负载,而无需进行自定义内核安装。
如何收集细粒度的系统信息?
strace 工具可用于跟踪进程发出的系统调用和接收的信号。系统调用是应用程序与操作系统内核之间的基本接口。它们使程序能够向内核请求服务。例如,在 Linux 中,open() 系统调用用于提供对文件系统中文件的访问。strace 使我们能够跟踪应用程序发出的所有系统调用。它列出了进程发出的所有系统调用及其结果输出。
您可以使用结合 strace 和 perf record 工具生成分析数据,以记录与进程相关的事件和信息。这提供了对进程的洞察。"perf annotate" 工具生成程序的每条指令的统计信息。本文详细介绍了如何收集工作负载对系统资源的细粒度使用信息。
我们使用 strace 来追踪 perf、stress-ng、paxtest 工作负载,以说明我们发现工作负载使用的资源的方法。这个过程可以应用于追踪其他工作负载。
为追踪做好准备
在开始之前,我们将向您展示如何准备您的系统。我们假设您的系统运行在物理系统或虚拟机上的 Linux 发行版上。大多数发行版都包含 strace 命令。让我们安装其他通常不包含在内核构建中的工具。请注意,以下操作适用于基于 Debian 的发行版。您可能需要在其他 Linux 发行版上找到相应的软件包。
安装构建 Linux 内核和内核存储库中的工具所需的工具。scripts/ver_linux 是检查系统是否已经具备必要工具的好方法:
sudo apt-get build-essentials flex bison yacc sudo apt install libelf-dev systemtap-sdt-dev libaudit-dev libslang2-dev libperl-dev libdw-dev
cscope 是浏览内核源代码的好工具。现在让我们安装它:
sudo apt-get install cscope
安装 stress-ng 和 paxtest:
apt-get install stress-ng apt-get install paxtest
工作负载概述
如前所述,我们使用 strace 来追踪 perf bench、stress-ng 和 paxtest 工作负载,以展示如何分析工作负载并识别这些工作负载使用的 Linux 子系统。让我们从这三个工作负载的概述开始,以更好地了解它们的功能和如何使用它们。
perf bench(all)工作负载
perf bench 命令包含多个多线程微内核基准测试,用于执行 Linux 内核和系统调用中的不同子系统。这使我们能够轻松地测量变更的影响,有助于减轻性能回归。它还充当一个通用的基准测试框架,使开发人员能够轻松创建测试用例,透明地集成,并使用性能丰富的工具子系统。
Stress-ng netdev stressor 工作负载
stress-ng 用于对内核进行压力测试。它允许您通过 "stressor-s" 来测试计算机的各种物理子系统,以及操作系统内核的接口。它们适用于 CPU、CPU 缓存、设备、I/O、中断、文件系统、内存、网络、操作系统、管道、调度器和虚拟机。请参阅 stress-ng 手册以找到所有可用 stressor-s 的描述。netdev stressor 启动指定数量(N)的工作程序,通过所有可用的网络设备执行各种 netdevice ioctl 命令。
paxtest kiddie 工作负载
paxtest 是一个测试内核中缓冲区溢出的程序。它测试内核对内存使用的执行。通常,某些内存段中的执行可能导致缓冲区溢出。它运行一组试图破坏内存使用的程序。它用作 PaX 的回归测试套件,但可能对测试内核的其他内存保护补丁也有用。我们使用了 paxtest kiddie 模式,该模式寻找简单的漏洞。
什么是 strace,如何使用它?
如前所述,strace 是一种有用的诊断、指导和调试工具,可用于发现工作负载使用的系统资源。它可以用于:
- 查看进程与内核的交互方式。
- 查看进程失败或挂起的原因。
- 对进程进行逆向工程。
- 查找程序依赖的文件。
- 分析应用程序的性能。
- 解决与操作系统相关的各种问题。
此外,strace 可以为每个系统调用生成运行时统计信息,包括时间、调用次数和错误,并在程序退出时报告摘要,抑制常规输出。这试图显示系统时间(在内核中运行的 CPU 时间)与挂钟时间无关。我们计划使用这些功能来获取有关工作负载系统使用情况的信息。
strace 命令支持基本、详细和统计模式。以详细模式运行的 strace 命令会提供有关进程调用的系统调用的更详细信息。
运行 strace -c 会生成每个系统调用所花费时间的百分比报告,总时间(秒),每次调用的微秒数,调用的总次数,失败的每个系统调用的计数以及所做系统调用的类型。
- 使用:strace <要追踪的命令>
- 详细模式使用:strace -v <命令>
- 收集统计信息:strace -c <命令>
我们使用了“-c”选项来收集我们选择用于分析的三个工作负载的细粒度运行时统计信息。
- perf
- stress-ng
- paxtest
什么是 cscope,如何使用它?
现在让我们来看看 cscope,这是一个用于浏览 C、C++ 或 Java 代码库的命令行工具。我们可以使用它来查找符号的所有引用、全局定义、被一个函数调用的函数、调用一个函数的函数、文本字符串、正则表达式模式、包含一个文件的文件。
我们可以使用 cscope 找出哪个系统调用属于哪个子系统。这样我们就可以在执行进程时找到进程使用的内核子系统。
让我们检出最新的 Linux 存储库并构建 cscope 数据库:
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git linux cd linux cscope -R -p10 # 在开始浏览会话之前构建 cscope.out 数据库 cscope -d -p10 # 在 cscope.out 数据库上开始浏览会话
注意:运行 "cscope -R -p10" 来构建数据库,运行 "cscope -d -p10" 进入浏览会话。cscope 默认使用 cscope.out 数据库。要退出此模式,请按下 ctrl+d。-p 选项用于指定要显示的文件路径组件的数量。-p10 对于浏览内核源代码是最佳的。
什么是 perf,如何使用它?
Perf 是基于 Linux 2.6+ 系统的分析工具,它在 Linux 中抽象了 CPU 硬件差异的性能测量,并提供了一个简单的命令行界面。Perf 基于内核导出的 perf_events 接口。它非常有用,可以对系统进行分析,并找出应用程序中的性能瓶颈。
如果您还没有检出 Linux 主线存储库,您可以这样做,然后构建内核和 perf 工具:
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git linux cd linux make -j3 all cd tools/perf make
注意:perf 命令可以在不构建存储库的情况下构建,并且可以在旧内核上运行。但是,匹配内核和 perf 版本可以更准确地提供子系统使用的信息。
我们使用了 "perf stat" 和 "perf bench" 选项。要获取有关 perf 工具的详细信息,请运行 "perf -h"。
perf stat
perf stat命令生成各种硬件和软件事件的报告。它利用现代CPU中的硬件计数器寄存器来记录这些活动的计数。"perf stat cal"显示cal命令的统计信息。
Perf bench
perf bench命令包含多个多线程微内核基准测试,用于执行Linux内核和系统调用中的不同子系统。这使我们能够轻松地测量变化的影响,有助于减轻性能退化。它还充当一个通用的基准测试框架,使开发人员能够轻松创建测试用例,透明地集成,并使用性能丰富的工具。
"perf bench all"命令运行以下基准测试:
- sched/messaging
- sched/pipe
- syscall/basic
- mem/memcpy
- mem/memset
stress-ng是什么,如何使用它?
如前所述,stress-ng用于对内核进行压力测试。它允许您通过stressor对计算机的各种物理子系统以及操作系统内核的接口进行测试。它们适用于CPU、CPU缓存、设备、I/O、中断、文件系统、内存、网络、操作系统、管道、调度程序和虚拟机。
netdev stressor启动N个工作线程,通过所有可用的网络设备执行各种netdevice ioctl命令。以下ioctl被执行:
- SIOCGIFCONF
- SIOCGIFINDEX
- SIOCGIFNAME
- SIOCGIFFLAGS
- SIOCGIFADDR
- SIOCGIFNETMASK
- SIOCGIFMETRIC
- SIOCGIFMTU
- SIOCGIFHWADDR
- SIOCGIFMAP
- SIOCGIFTXQLEN
以下命令运行stressor:
stress-ng --netdev 1 -t 60 --metrics command
我们可以使用perf record命令记录与进程相关的事件和信息。该命令将在相同目录中的perf.data文件中记录分析数据。
使用以下命令,您可以记录与netdev stressor相关的事件,查看生成的报告perf.data,并注释以查看程序的每条指令的统计信息:
perf record stress-ng --netdev 1 -t 60 --metrics command perf report perf annotate
paxtest是什么,如何使用它?
paxtest是一个测试内核中缓冲区溢出的程序。它测试内核对内存使用的执行。通常,某些内存段中的执行使得缓冲区溢出成为可能。它运行一组试图破坏内存使用的程序。它用作PaX的回归测试套件,并且对于测试内核的其他内存保护补丁也很有用。
paxtest提供kiddie和blackhat模式。paxtest kiddie模式以正常模式运行,而blackhat模式试图绕过内核的保护,测试漏洞。我们在这里关注kiddie模式,并将"paxtest kiddie"运行与"perf record"结合起来,以收集paxtest kiddie运行的CPU堆栈跟踪,以查看性能配置文件中的哪些函数调用其他函数。然后可以使用"dwarf"(DWARF的调用帧信息)模式展开堆栈。
以下命令可用于以调用图格式查看生成的报告:
perf record --call-graph dwarf paxtest kiddie perf report --stdio
跟踪工作负载
现在我们了解了工作负载,让我们开始跟踪它们。
跟踪perf bench all工作负载
运行以下命令以跟踪perf bench all工作负载:
strace -c perf bench all
工作负载所发出的系统调用
下表显示了工作负载调用的系统调用、每个系统调用被调用的次数以及相应的Linux子系统。
系统调用 | # 调用 | Linux子系统 | 系统调用(API) |
getppid | 10000001 | 进程管理 | sys_getpid() |
clone | 1077 | 进程管理 | sys_clone() |
prctl | 23 | 进程管理 | sys_prctl() |
prlimit64 | 7 | 进程管理 | sys_prlimit64() |
... | ... | ... | ... |
(表格内容较多,省略部分)
跟踪stress-ng netdev stressor工作负载
运行以下命令以跟踪stress-ng netdev stressor工作负载:
strace -c stress-ng --netdev 1 -t 60 --metrics
工作负载所发出的系统调用
下表显示了工作负载调用的系统调用、每个系统调用被调用的次数以及相应的Linux子系统。
系统调用 | # 调用 | Linux子系统 | 系统调用(API) |
openat | 74 | 文件系统 | sys_openat() |
close | 75 | 文件系统 | sys_close() |
read | 58 | 文件系统 | sys_read() |
... | ... | ... | ... |
(表格内容较多,省略部分)
跟踪paxtest kiddie工作负载
运行以下命令以跟踪paxtest kiddie工作负载:
strace -c paxtest kiddie
工作负载所发出的系统调用
下表显示了工作负载调用的系统调用、每个系统调用被调用的次数以及相应的Linux子系统。
系统调用 | # 调用 | Linux子系统 | 系统调用(API) |
read | 3 | 文件系统 | sys_read() |
write | 11 | 文件系统 | sys_write() |
close | 41 | 文件系统 | sys_close() |
... | ... | ... |
结论
本文档旨在作为如何使用 strace 收集工作负载使用的资源的细粒度信息的指南。