用户态调测工具(一):strace和ltrace

简单科普:Linux的用户态和内核态

Linux操作系统的体系架构分为用户态和内核态(或者用户空间和内核)。内核从本质上看是一种软件–控制计算机的硬件资源,并提供上层应用程序运行的环境。
用户态即上层应用程序的活动空间,应用程序的执行必须依托于内核提供的资源,包括CPU资源、存储资源、I/O资源等。为了使上层应用能够访问到这些资源,内核必须为上层应用提供访问的接口:即系统调用。
一般来说系统调用经过:用户调用syscall->glibc库->内核执行,返回值->glibc库->syscall->用户。
除非内核提供接口,否则用户态无法访问到内核资源。

Strace常用来跟踪进程在用户态执行的系统调用流程,单不会跟踪到内核里面发生的事情(顺便提一句,内核里面用ftrace)。

输出含义

以strace ls为例:

$ strace ls
execve("/bin/ls", ["ls"], [/* 26 vars */]) = 0
brk(NULL) = 0x1ad4000
access("/etc/ld.so.nohwcap", FOK) = -1 ENOENT (No such file or directory) mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f397bd49000 access("/etc/ld.so.preload", ROK) = 0

每一行都是一条系统调用,包含调用函数,函数参数,函数返回值,但不会显示内核的系统调用和流程。

参数

说明:随着系统的不同和工具包的升级,不同环境命令支持情况也不相同,个人最好养成查看命令帮助使用command –help的习惯。

-c 统计每一系统调用的所执行的时间,次数和出错的次数等.
-d 输出strace关于标准错误的调试信息.
-f 跟踪由fork调用所产生的子进程.
-ff 如果提供-o filename,则所有进程的跟踪结果输出到相应的filename.pid中,pid是各进程的进程号.
-F 尝试跟踪vfork调用.在-f时,vfork不被跟踪.
-h 输出简要的帮助信息.
-i 输出系统调用的入口指针.
-q 禁止输出关于脱离的消息.
-r 打印出相对时间关于,,每一个系统调用.
-t 在输出中的每一行前加上时间信息.
-tt 在输出中的每一行前加上时间信息,微秒级.
-ttt 微秒级输出,以秒了表示时间.
-T 显示每一调用所耗的时间.
-v 输出所有的系统调用.一些调用关于环境变量,状态,输入输出等调用由于使用频繁,默认不输出.
-V 输出strace的版本信息.
-x 以十六进制形式输出非标准字符串
-xx 所有字符串以十六进制形式输出.
-a column
设置返回值的输出位置.默认 为40.
-e expr
指定一个表达式,用来控制如何跟踪.格式如下:
[qualifier=][!]value1[,value2]…
qualifier只能是 trace,abbrev,verbose,raw,signal,read,write其中之一.value是用来限定的符号或数字.默认的 qualifier是 trace.感叹号是否定符号.例如:
-eopen等价于 -e trace=open,表示只跟踪open调用.而-etrace!=open表示跟踪除了open以外的其他调用.有两个特殊的符号 all 和 none.
注意有些shell使用!来执行历史记录里的命令,所以要使用\.
-e trace=set
只跟踪指定的系统 调用.例如:-e trace=open,close,rean,write表示只跟踪这四个系统调用.默认的为set=all.
-e trace=file
只跟踪有关文件操作的系统调用.
-e trace=process
只跟踪有关进程控制的系统调用.
-e trace=network
跟踪与网络有关的所有系统调用.
-e strace=signal
跟踪所有与系统信号有关的 系统调用
-e trace=ipc
跟踪所有与进程通讯有关的系统调用
-e abbrev=set
设定 strace输出的系统调用的结果集.-v 等与 abbrev=none.默认为abbrev=all.
-e raw=set
将指 定的系统调用的参数以十六进制显示.
-e signal=set
指定跟踪的系统信号.默认为all.如 signal=!SIGIO(或者signal=!io),表示不跟踪SIGIO信号.
-e read=set
输出从指定文件中读出 的数据.例如:
-e read=3,5
-e write=set
输出写入到指定文件中的数据.
-o filename
将strace的输出写入文件filename
-p pid
跟踪指定的进程pid.
-s strsize
指定输出的字符串的最大长度.默认为32.文件名一直全部输出.
-u username
以username 的UID和GID执行被跟踪的命令

内容解析(strace ls为例)

一般strace的打印内容,我会作为3块来看:
1)系统环境调用,主要是加载命令或二进制所依赖的环境和库

execve("/bin/ls", ["ls"], [/* 26 vars /]) = 0 brk(NULL) = 0xd9f000 
access("/etc/ld.so.nohwcap", FOK) = -1 ENOENT (No such file or directory) 
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8f45df5000 access("/etc/ld.so.preload", ROK) = 0
加载系统/etc里面的配置文件
access("/etc/ld.so.nohwcap", FOK) = -1 ENOENT (No such file or directory) 
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|OCLOEXEC) = 3
加载libc.so C库

2)该命令和二进制执行流程

open(".", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFDIR|0775, stsize=4096, …}) = 0 getdents(3, / 4 entries /, 32768) = 120 getdents(3, / 0 entries */, 32768) = 0
close(3) = 0
fstat(1, {st_mode=S_IFREG|0664, stsize=8230, …}) = 0
write(1, "log\nmachinelearninginaction\n", 28log
machinelearninginaction
) = 28

我们可以看到,大概流程包括open当前目录、得到当前目录文件信息(名称、权限、大小等),打印到控制台
3)返回值

close(1) = 0
close(2) = 0
exit_group(0) = ?
+++ exited with 0 +++

正常则返回0,如果出现异常,会返回异常SIG。

个人认为主要用途

作为命令或可执行文件执行失败时,失败位置定位和失败原因查看的非常方便的工具。
个人常用作:
系统命令执行失败纠错;
某服务start/stop执行失败原因查看,比如未找到/etc/下配置文件,打开/etc/下配置文件失败(权限不够)等问题;
系统调用执行失败,如顺便可查看系统调用流程,失败位置,失败原因等;

6.对应工具ltrace
ltrace同strace作为用户态调测工具,打印进程的库函数调用,但个人不太常用:

memcpy(0x216e2a0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"…, 56) = 0x216e2a0
__errno_location() = 0x7f345a2476b8
malloc(56) = 0x216e2e0
memcpy(0x216e2e0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"…, 56) = 0x216e2e0
getenv("TZ") = nil
malloc(128) = 0x216e320
malloc(19200) = 0x216e3b0
malloc(32) = 0x216d090

这里写图片描述

猜你喜欢

转载自blog.csdn.net/cui841923894/article/details/81395572