内核调试工具——strace
简介
strace常用来跟踪进程执行时的系统调用和所接收的信号。 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式,通 过系统调用访问硬件设备。strace可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间。
输出参数含义
- [root@localhost ~]# strace cat /dev/null
- execve("/bin/cat", ["cat", "/dev/null"], [/* 46 vars */]) =
- brk() = 0x9bfb000
- mmap2(NULL, , PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -, ) = 0xb772a000
- access("/etc/ld.so.preload", R_OK) = - ENOENT (No such file or directory)
- open("tls/i686/sse2/libc.so.6", O_RDONLY) = - ENOENT (No such file or directory)
- open("tls/i686/libc.so.6", O_RDONLY) = - ENOENT (No such file or directory)
- open("tls/sse2/libc.so.6", O_RDONLY) = - ENOENT (No such file or directory)
- open("tls/libc.so.6", O_RDONLY) = - ENOENT (No such file or directory)
- open("i686/sse2/libc.so.6", O_RDONLY) = - ENOENT (No such file or directory)
- open("i686/libc.so.6", O_RDONLY) = - ENOENT (No such file or directory)
- open("sse2/libc.so.6", O_RDONLY) = - ENOENT (No such file or directory)
- open("libc.so.6", O_RDONLY) = - ENOENT (No such file or directory)
- open("/opt/wx/2.8/lib/tls/i686/sse2/libc.so.6", O_RDONLY) = - ENOENT (No such file or directory)
- stat64("/opt/wx/2.8/lib/tls/i686/sse2", 0xbfc03390) = - ENOENT (No such file or directory)
- open("/opt/wx/2.8/lib/tls/i686/libc.so.6", O_RDONLY) = - ENOENT (No such file or directory)
- stat64("/opt/wx/2.8/lib/tls/i686", 0xbfc03390) = - ENOENT (No such file or directory)
- open("/opt/wx/2.8/lib/tls/sse2/libc.so.6", O_RDONLY) = - ENOENT (No such file or directory)
- stat64("/opt/wx/2.8/lib/tls/sse2", 0xbfc03390) = - ENOENT (No such file or directory)
- open("/opt/wx/2.8/lib/tls/libc.so.6", O_RDONLY) = - ENOENT (No such file or directory)
- stat64("/opt/wx/2.8/lib/tls", 0xbfc03390) = - ENOENT (No such file or directory)
- open("/opt/wx/2.8/lib/i686/sse2/libc.so.6", O_RDONLY) = - ENOENT (No such file or directory)
- stat64("/opt/wx/2.8/lib/i686/sse2", 0xbfc03390) = - ENOENT (No such file or directory)
- open("/opt/wx/2.8/lib/i686/libc.so.6", O_RDONLY) = - ENOENT (No such file or directory)
- stat64("/opt/wx/2.8/lib/i686", 0xbfc03390) = - ENOENT (No such file or directory)
- open("/opt/wx/2.8/lib/sse2/libc.so.6", O_RDONLY) = - ENOENT (No such file or directory)
- stat64("/opt/wx/2.8/lib/sse2", 0xbfc03390) = - ENOENT (No such file or directory)
- open("/opt/wx/2.8/lib/libc.so.6", O_RDONLY) = - ENOENT (No such file or directory)
- stat64("/opt/wx/2.8/lib", {st_mode=S_IFDIR|, st_size=, ...}) =
- open("/etc/ld.so.cache", O_RDONLY) =
- fstat64(, {st_mode=S_IFREG|, st_size=, ...}) =
- mmap2(NULL, , PROT_READ, MAP_PRIVATE, , ) = 0xb7716000
- close() =
- open("/lib/libc.so.6", O_RDONLY) =
- read(, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220n\1\0004\0\0\0"..., ) =
- fstat64(, {st_mode=S_IFREG|, st_size=, ...}) =
- mmap2(NULL, , PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, , ) = 0xe45000
- mmap2(0xfd5000, , PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, , 0x190) = 0xfd5000
- mmap2(0xfd8000, , PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -, ) = 0xfd8000
- close() =
- mmap2(NULL, , PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -, ) = 0xb7715000
- set_thread_area({entry_number:- -> , base_addr:0xb77156c0, limit:, seg_32bit:, contents:, read_exec_only:, limit_in_pages:, seg_not_present:, useable:}) =
- mprotect(0xfd5000, , PROT_READ) =
- mprotect(0x2b0000, , PROT_READ) =
- munmap(0xb7716000, ) =
- brk() = 0x9bfb000
- brk(0x9c1c000) = 0x9c1c000
- open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE) =
- fstat64(, {st_mode=S_IFREG|, st_size=, ...}) =
- mmap2(NULL, , PROT_READ, MAP_PRIVATE, , ) = 0xb7515000
- mmap2(NULL, , PROT_READ, MAP_PRIVATE, , 0x2eb5) = 0xb74d5000
- mmap2(NULL, , PROT_READ, MAP_PRIVATE, , 0x326f) = 0xb7381000
- close() =
- fstat64(, {st_mode=S_IFCHR|, st_rdev=makedev(, ), ...}) =
- open("/dev/null", O_RDONLY|O_LARGEFILE) =
- fstat64(, {st_mode=S_IFCHR|, st_rdev=makedev(, ), ...}) =
- read(, "", ) =
- close() =
- close() =
- close() =
- exit_group() = ?
每一行都是一条系统调用,等号左边是系统调用的函数名及其参数,右边是该调用的返回值。strace的大多数输出显示了对mmap()和open()的调用,采用类似ld.so和libc这样的文件名。它们与一般系统级操作有关,比如将磁盘文件映射到内存中及加载共享库等。
strace 显示这些调用的参数并返回符号形式的值。strace 从内核接收信息,而且不需要以任何特殊的方式来构建内核。
strace参数
- -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=,
- -e write=set
- 输出写入到指定文件中的数据.
- -o filename
- 将strace的输出写入文件filename
- -p pid
- 跟踪指定的进程pid.
- -s strsize
- 指定输出的字符串的最大长度.默认为32.文件名一直全部输出.
- -u username
- 以username 的UID和GID执行被跟踪的命令
命令实例
通用的完整用法:
- strace -o output.txt -T -tt -e trace=all -p
上面的含义是 跟踪28979进程的所有系统调用(-e trace=all),并统计系统调用的花费时间,以及开始时间(并以可视化的时分秒格式显示),最后将记录结果存在output.txt文件里面。
strace案例
解决库依赖问题
starce 的另一个用处是解决和动态库相关的问题。当对一个可执行文件运行ldd时,它会告诉你程序使用的动态库和找到动态库的位置。但是如果你正在使用一个比较老 的glibc版本(2.2或更早),你可能会有一个有bug的ldd程序,它可能会报告在一个目录下发现一个动态库,但是真正运行程序时动态连接程序 (/lib/ld-linux.so.2)却可能到另外一个目录去找动态连接库。这通常因为/etc/ld.so.conf和 /etc/ld.so.cache文件不一致,或者/etc/ld.so.cache被破坏。在glibc 2.3.2版本上这个错误不会出现,可能ld-linux的这个bug已经被解决了。
尽管这样,ldd并不能把所有程序依赖的动态库列出 来,系统调用dlopen可以在需要的时候自动调入需要的动态库,而这些库可能不会被ldd列出来。作为glibc的一部分的NSS(Name Server Switch)库就是一个典型的例子,NSS的一个作用就是告诉应用程序到哪里去寻找系统帐号数据库。应用程序不会直接连接到NSS库,glibc则会通 过dlopen自动调入NSS库。如果这样的库偶然丢失,你不会被告知存在库依赖问题,但这样的程序就无法通过用户名解析得到用户ID了。让我们看一个例子:
whoami程序会给出你自己的用户名,这个程序在一些需要知道运行程序的真正用户的脚本程序里面非常有用,whoami的一个示例 输出如下:
- # whoami
- root
假设因为某种原因在升 级glibc的过程中负责用户名和用户ID转换的库NSS丢失,我们可以通过把nss库改名来模拟这个环境:
- # mv /lib/libnss_files.so. /lib/libnss_files.so..backup
- # whoami
- whoami: cannot find username for UID
这里你可以看到,运行whoami时出现了错误,ldd程序的输出不会提供有用的帮助:
- # ldd /usr/bin/whoami
- libc.so. => /lib/libc.so. (0x4001f000)
- /lib/ld-linux.so. => /lib/ld-linux.so. (0x40000000)
你只会看到whoami依赖Libc.so.6和ld-linux.so.2,它没有给出运行whoami所必须的其他库。这里时用strace跟踪 whoami时的输出:
- strace -o whoami-strace.txt whoami
- open("/lib/libnss_files.so.2", O_RDONLY) = - ENOENT (No such file or directory)
- open("/lib/i686/mmx/libnss_files.so.2", O_RDONLY) = - ENOENT (No such file or directory)
- stat64("/lib/i686/mmx", 0xbffff190) = - ENOENT (No such file or directory)
- open("/lib/i686/libnss_files.so.2", O_RDONLY) = - ENOENT (No such file or directory)
- stat64("/lib/i686", 0xbffff190) = - ENOENT (No such file or directory)
- open("/lib/mmx/libnss_files.so.2", O_RDONLY) = - ENOENT (No such file or directory)
- stat64("/lib/mmx", 0xbffff190) = - ENOENT (No such file or directory)
- open("/lib/libnss_files.so.2", O_RDONLY) = - ENOENT (No such file or directory)
- stat64("/lib", {st_mode=S_IFDIR|, st_size=, ...}) =
- open("/usr/lib/i686/mmx/libnss_files.so.2", O_RDONLY) = - ENOENT (No such file or directory)
- stat64("/usr/lib/i686/mmx", 0xbffff190) = - ENOENT (No such file or directory)
- open("/usr/lib/i686/libnss_files.so.2", O_RDONLY) = - ENOENT (No such file or directory)
你可以发现在不同目录下面查找libnss.so.2的尝试,但是都失败了。如果没有strace这样的工具,很难发现这个错误是由于缺少动态库造成的。现 在只需要找到libnss.so.2并把它放回到正确的位置就可以了。
限制strace只跟踪特定的系统调用
如果你已经知道你要找什么,你可以让strace只跟踪一些类型的系统调用。例如,你需要看看在configure脚本里面执行的程序,你需要监视的系统调 用就是execve。让strace只记录execve的调用用这个命令:
- strace -f -o configure-strace.txt -e execve ./configure
转载:http://www.cnblogs.com/ggjucheng/archive/2012/01/08/2316692.html
内核调试工具——strace的更多相关文章
- Linux调试工具strace和gdb常用命令小结
strace和gdb是Linux环境下的两个常用调试工具,这里是个人在使用过程中对这两个工具常用参数的总结,留作日后查看使用. strace调试工具 strace工具用于跟踪进程执行时的系统调用和所接 ...
- 转 -Linux 自检和 SystemTap (强大的内核调试工具)---包含下载地址
下载: http://www.oschina.net/p/systemtap/ https://sourceware.org/systemtap/ftp/releases/ Linux 自检和 S ...
- 内核调试工具 — kdump & crash
kdump简介 kdump是系统崩溃的时候,用来转储运行内存的一个工具. 系统一旦崩溃,内核就没法正常工作了,这个时候将由kdump提供一个用于捕获当前运行信息的内核, 该内核会将此时内存中的所有运行 ...
- 使用kdump内核调试工具遇到的问题及解决
修改linux内核代码或者内核模块的时候,搞不好就会造成linux死机崩溃,crash死机后/var/log/kern.log里面不会有任何异常信息记录.这时候kdump就会派上用场了,网上kdump ...
- Linux strace命令
简介 strace常用来跟踪进程执行时的系统调用和所接收的信号. 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核 ...
- 转 strace
转自http://www.cnblogs.com/ggjucheng/archive/2012/01/08/2316692.html strace常用来跟踪进程执行时的系统调用和所接收的信号. 在Li ...
- strace命令介绍(转)
原文链接:http://www.cnblogs.com/ggjucheng/archive/2012/01/08/2316692.html 简介 strace常用来跟踪进程执行时的系统调用和所接收的信 ...
- Linux内核调试方法总结【转】
转自:http://my.oschina.net/fgq611/blog/113249 内核开发比用户空间开发更难的一个因素就是内核调试艰难.内核错误往往会导致系统宕机,很难保留出错时的现场.调试内核 ...
- strace命令
简介 strace常用来跟踪进程执行时的系统调用和所接收的信号. 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核 ...
随机推荐
- Spring cloud Zuul网关异常处理
Spring cloud Zuul网关异常处理 一 异常测试: 1> 创建一个pre类型的过滤器,并在该过滤器的run方法实现中抛出一个异常.比如下面的实现,在run方法中调用的doSometh ...
- mac上调整phpstorm和webstorm的使用内存(默认是128m-750m) 避免卡顿
For Mac Only WebStorm/phpstrom用起来一卡一卡,如今才发现是它的默认内存配置太弱.修改之: 修改phpstrom vi /Applications/PhpStorm.app ...
- apache配置域名访问本地空间
1. 首先修改C盘WINDOWS\system32\drivers\etc目录下的 hosts 文件,用记事本打开,加入: 127.0.0.1 www.a.com hosts文件是用来解析的,你在浏览 ...
- JavaScript中的__proto__
实例中的__proto__ 箭头函数的__proto__ 需要注意的是箭头函数的__proto__并没有指向Function构造函数的的原型对象 MDN上的资料显示,箭头函数不绑定Arguments ...
- Project Euler 44: Find the smallest pair of pentagonal numbers whose sum and difference is pentagonal.
In Problem 42 we dealt with triangular problems, in Problem 44 of Project Euler we deal with pentago ...
- 打通版微社区(5):部署DZ3.2
参考官方帖子http://www.discuz.net/thread-3258186-1-1.html 这是第三方的帖子http://www.discuz.net/thread-3199850-1- ...
- 文件复制(shutil)
import shutil #拷贝整个目录树 shutil.copytree('d:\\aaa','e:\\aaa') #目标文件夹(e:\aaa)必须不存在 shutil.rmtree('e:\\a ...
- React学习笔记(五)State&声明周期
React学习笔记(五) 四.State&声明周期 可以为组件添加"状态(state)".状态与属性相似,但是状态是私有的,完全受控于当前组件. 局部状态就是只能用于类(定 ...
- MySQL 数据库--索引原理与慢查询优化
索引的原理 本质都是:通过不断地缩小想要获取数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件,也就是说,有了这种索引机制,我们可以总是用同一种查找方式来锁定数据. 索引的数据结构 b+ ...
- windows系统镜像 微软官方资源便捷下载教程
今天跟小师弟学到了一个下载软件的好办法,省得到各种网站下载带有病毒,插件的资源. 这个神奇的网站叫做 MSDN, 我告诉你,这是一个私人维护的网站,里面有各种官方软件的下载地址.可以直接用下载工具 ...