通过这篇文章你会学习到strace的用法,strace可以帮助你高效地定位进程中的一些错误,关于strace的用处有很多,可以自行发掘

前面我们讲解了gdb调试程序,这篇文章介绍另一个调试跟踪工具strace,同样你可以在linux下执行man strace查看帮助信息

(一)starce是什么

我们直接看man打印的帮助信息

 strace - trace system calls and signals

根据上面的描述我们可以知道strace主要是跟踪系统的调用和信号的传递,其实我们还可以用它来监视用户进程和内核的交互,它能通过系统调用来侦测程序运行的详细过程

在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式,通 过系统调用访问硬件设备。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 所有字符串以十六进制形式输出.

-e expr :指定一个表达式,用来控制如何跟踪,由于格式比较多我们单独拿出来

格式如下:

[qualifier=][!]value1[,value2]...

qualifier只能是 trace,abbrev,verbose,raw,signal,read,write其中之一.value是用来限定的符号或数字.默认的 qualifier是 trace.感叹号是否定符号.

-e expr 参数设置
-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 输出从指定文件中读出 的数据.例如:
-o filename 将strace的输出写入文件filename
-p pid 跟踪指定的进程pid.
-s strsize 指定输出的字符串的最大长度.默认为32.文件名一直全部输出.
-u username 以username 的UID和GID执行被跟踪的命令

示例:
(1)根据指定pid进程跟踪

strace -o output.txt -T -tt -e trace=all -p 28979

上面的含义是 跟踪28979进程的所有系统调用(-e trace=all),并统计系统调用的花费时间,以及开始时间(并以可视化的时分秒格式显示),最后将记录结果存在output.txt文件里面。
(2)根据进程名跟踪

strace -o output.txt -T -tt -e trace=all  ./a.out

(三)strace的一个分析实例

test.c

#include <stdio.h>
#include <unistd.h>int main(int argc,char * argv[])
{char buff[256]={0};FILE* file=NULL;file=fopen(argv[1],"r");if(file == NULL){printf("fopen error\n");
//     return -1;}fread(buff,sizeof(buff),1,file);printf("buff=%s\n",buff);return 0;
}

我们执行:

gcc test.c -o test
./test

上面我们执行时不输入任何参数,肯定会报段错误

fopen error
段错误 (核心已转储)

我们这里使用strace查看信息:

root@lvirtual-machine:~/test# strace  -T -tt -e trace=all  ./test
22:32:53.349314 execve("./test", ["./test"], [/* 60 vars */]) = 0 <0.000440>
22:32:53.350129 brk(NULL)               = 0xb3f000 <0.000097>
22:32:53.350417 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) <0.000094>
22:32:53.350769 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) <0.000062>
22:32:53.351014 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 <0.000127>
22:32:53.351316 fstat(3, {st_mode=S_IFREG|0644, st_size=96373, ...}) = 0 <0.000105>
22:32:53.351585 mmap(NULL, 96373, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f0bec216000 <0.000065>
22:32:53.351793 close(3)                = 0 <0.000052>
22:32:53.352046 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) <0.000068>
22:32:53.352313 open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 <0.000106>
22:32:53.352597 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\t\2\0\0\0\0\0"..., 832) = 832 <0.000061>
22:32:53.352789 fstat(3, {st_mode=S_IFREG|0755, st_size=1868984, ...}) = 0 <0.000110>
22:32:53.353092 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0bec215000 <0.000122>
22:32:53.353409 mmap(NULL, 3971488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f0bebc3f000 <0.000117>
22:32:53.353629 mprotect(0x7f0bebdff000, 2097152, PROT_NONE) = 0 <0.000115>
22:32:53.353841 mmap(0x7f0bebfff000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c0000) = 0x7f0bebfff000 <0.000110>
22:32:53.354073 mmap(0x7f0bec005000, 14752, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0bec005000 <0.000060>
22:32:53.354297 close(3)                = 0 <0.000035>
22:32:53.354556 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0bec214000 <0.000060>
22:32:53.354736 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0bec213000 <0.000045>
22:32:53.354888 arch_prctl(ARCH_SET_FS, 0x7f0bec214700) = 0 <0.000040>
22:32:53.355125 mprotect(0x7f0bebfff000, 16384, PROT_READ) = 0 <0.000051>
22:32:53.355288 mprotect(0x600000, 4096, PROT_READ) = 0 <0.000050>
22:32:53.355487 mprotect(0x7f0bec22e000, 4096, PROT_READ) = 0 <0.000085>
22:32:53.355724 munmap(0x7f0bec216000, 96373) = 0 <0.000094>
22:32:53.356015 brk(NULL)               = 0xb3f000 <0.000072>
22:32:53.356203 brk(0xb60000)           = 0xb60000 <0.000075>
22:32:53.356426 open(NULL, O_RDONLY)    = -1 EFAULT (Bad address) <0.000078>
22:32:53.356664 fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 11), ...}) = 0 <0.000065>
22:32:53.356879 write(1, "fopen error\n", 12fopen error
) = 12 <0.000065>
22:32:53.357116 --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0} ---
22:32:53.542212 +++ killed by SIGSEGV (core dumped) +++
段错误 (核心已转储)

上面输出的信息非常多,但是我们可以找到我们需要的

open(NULL, O_RDONLY)    = -1 EFAULT (Bad address)

我们使用starce也就是根据这些系统调用去过滤出我们需要的信息


当我们发现程序运行异常时,我们可以使用strace来跟踪其系统调用,看看这些系统调用有没有异常,进而找到异常的原因。

调试跟踪利器---strace相关推荐

  1. strace跟踪java,linux运维利器—–strace命令

    strace常用来跟踪进程执行时的系统调用和所接收的信号. 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式 ...

  2. DSTREAM-PT仿真器——ARM公司推出的最高性能的调试跟踪解决方案

    2019年4月,ARM公司推出最高性能的调试跟踪解决方案--DSTREAM-PT. DSTREAM-PT具有高性能调试和跟踪功能,快速下载特点,是自适应JTAG时钟速率和并行流跟踪的理想选择. DST ...

  3. php执行跟踪_PHP 代码调试跟踪工具 Ytrace

    Ytrace是一个PHP代码调试跟踪工具,通过将PHP代码执行过程记录到文件中,再通过webui界面展示出来,并且支持单步调试的方式去查看执行过程. 主要特性: 可以可视化的看到源码文件哪些行被执行了 ...

  4. mysql innodb源代码调试跟踪分析 何登成_Mysql+Innodb源代码调试跟踪分析+何登成_IT168文库...

    Mysql+Innodb源代码调试跟踪分析+何登成_IT168文库 Mysql Innodb源代码调试跟踪分析 何登成 1 2 3 4 5 6 7 8 9 10 10.1 10.2 10.3 10.4 ...

  5. 标 题: 又灌水-反(调试/跟踪/脱壳) 技术集锦

    标 题: 又灌水-反(调试/跟踪/脱壳) 技术集锦 发信人: kongfoo 时 间: 2004-05-27,14:50 详细信息: 反(调试/跟踪/脱壳) 技术集锦 kongfoo/2004.4.1 ...

  6. Linux调试分析诊断利器----strace

    strace是个功能强大的Linux调试分析诊断工具,可用于跟踪程序执行时进程系统调用(system call)和所接收的信号,尤其是针对源码不可读或源码无法再编译的程序. 在Linux系统中,用户程 ...

  7. 应用调试之使用strace命令跟踪系统调用

    一.安装: 1.解压:tar xvf strace-4.5.15.tar.bz2 2.打补丁:cd strace-4.5.15 patch -p1 < ../strace-fix-arm-bad ...

  8. 【调试技巧】strace神器的使用方法详解与实践

    文章目录 1. Strace命令简介 2. 什么是系统调用 3. Strace的参数 4. Strace的基本用法 5. Strace实战示例 5.1 跟踪特定的系统调用 5.2 跟踪正在执行的程序 ...

  9. linux单步跟踪命令,dbx调试跟踪的常用子命令

    dbx是UNIX下基于命令行界面的程序调试器. dbx是通过交互执行dbx子命令来达到调试的目的的.在调试程序前,必须先将-g选项包含在编译信息中,编译生成带调试信息的文件,即:cc -o filen ...

最新文章

  1. PTA基础编程题目集-6-6 求单链表结点的阶乘和
  2. RK3288 手动设置电池电量
  3. hibernate教程--快速入门(增删改查)
  4. 把随机数对象暴露给window成为全局对象 原型及原型链 原型的指向是否可以改变
  5. 优雅的redux异步中间件 redux-effect
  6. tcpdump工具编译记录
  7. Linux的用户和组
  8. 面试官:你的缺点是什么?这样回答漂亮!
  9. Delta3D(7)教程:在场景编辑器中加载角色
  10. C# 简单的ZEBRA标签打印程序
  11. 【转】全国最佳医院排名
  12. Word 论文排版操作顺序
  13. LOJ 6198. 谢特(后缀数组+可持久化Trie)
  14. arm shell 获取本地键盘输入值_arm Linux 如何自动检测并mount SD卡,以及如何得知已经mount...
  15. 苹果设置显示连接到服务器,iPhone升级更新至iOS9后显示连接到iCloud服务器错误现象的解决办法...
  16. 根据汉字,获取拼音首字母(转)
  17. 从头到尾彻底理解傅里叶变换算法
  18. 博主联系方式汇总(非诚勿扰)
  19. SQL 查询当前时间,已经设置时区
  20. Linux用wget和curl下载jdk

热门文章

  1. c语言线性分类回归库 台湾,最全的线性回归算法库总结—— scikit-learn篇
  2. JMeter实现web接口测试实践举例
  3. jmeter 设置环境变量
  4. Vue + Spring Boot 项目实战(三):使用IntelliJ IDEA快速生成 Vue.js 项目
  5. flowable实战(四)flowable任务实例管理接口
  6. Maven出现.lastUpdated结尾的文件问题及解决
  7. linux 下载mysql5.7.22
  8. apache禁止多目录运行php文件下载,Nginx Apache下如何禁止指定目录运行PHP脚本
  9. ajax将数据显示在class为content的标签中_利用selenium实现自动翻页爬取某鱼数据
  10. Python break/continue - Python零基础入门教程