调试跟踪利器---strace

通过这篇文章你会学习到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来跟踪其系统调用,看看这些系统调用有没有异常,进而找到异常的原因。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/531353.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MBR、DBR、FAT32基础小知识

MBR-------主引导记录 1.创建时间&#xff1a;由分区软件&#xff08;Fdisk/PartitionMagic/Windows 2000/Windows XP安装 工具等&#xff09;给 硬盘分区时建立的。 2.功能 &#xff1a;存放硬盘分区信息和引导系统时检查分区。 3.作用范围&#xff1a;MBR和虚拟MBR控制着整个…

java使用Executor(执行器)管理线程

一.一个实现了Runnable接口的类 class MyThread implements Runnable{private static int num 0;Overridepublic void run() {while(true){synchronized(MyThread.class){num;try{Thread.sleep(500);} catch(Exception e){System.out.println(e.toString());}System.out.print…

JMM和happens-before原则

JMM&#xff1a; Java Memory Model(Java内存模型)&#xff0c;围绕着在并发过程中如何处理可见性、原子性、有序性这三个特性而建立的模型。 可见性&#xff1a; JMM提供了volatile变量定义、final、synchronized块来保证可见性。  例如&#xff1a;线程a在将共享变量x1写入…

SD卡移植FAT32文件系统无MBR

问题&#xff1a;在研究SD卡和FAT32文件系统的时候&#xff0c;发现SD卡有的有MBR&#xff0c;有的没有MBR&#xff0c;这个为什么呢&#xff1f; 分析&#xff1a;MBR是主引导记录&#xff0c;是在给磁盘分区的时候建立的&#xff0c;我们的SD卡没有这个可能就是没有进行过分区…

java获取类的信息

关键技术剖析 1.java.lang.reflect包实现了java的反射机制&#xff0c;在使用反射机制时&#xff0c;需要导入该包。 2.Class类的forName方法能够根据类名加载类&#xff0c;获得类的Class对象。 Class类的getSuperclass方法获得父类的Class对象&#xff1b;getDeclaredFields方…

FAT32文件系统介绍

FAT32文件系统&#xff08;一&#xff09;为什么要有文件系统&#xff08;二&#xff09;FAT32文件系统组成&#xff08;三&#xff09;分步介绍各部分(1) 首先介绍一下MBR(2)DBR介绍(3)FAT表介绍(4) 数据区&#xff08;一&#xff09;为什么要有文件系统 文件系统是操作系统用…

java中动态代理实现机制

前言&#xff1a; 代理模式是常用的java设计模式&#xff0c;它的特征是代理类与委托类有同样的接口&#xff0c;代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类&#xff0c;以及事后处理消息等。代理类与委托类之间通常会存在关联关系&#xff0c;一个代理类…

libiconv库简单裁剪支持CP437编码

有许多人在做项目的时候都会遇到字符编码的不一致导致的乱码问题&#xff0c;那如何去解决呢&#xff1f;在Linux系统上可以通过iconv函数族来进行编码转换&#xff0c;但有时候我们并不需要全部的字符集&#xff0c;因为可能会占用比较大的空间&#xff0c;本文主要支持CP437编…

简单java在线测评程序

简单java程序在线测评程序 一&#xff0e;前言 大家过年好&#xff01;今年的第一篇博客啊&#xff01;家里没有网&#xff0c;到处蹭无线&#xff01;日子过得真纠结&#xff01;因为毕设的需求&#xff0c;简单写了一个java程序在线测评程序&#xff0c;当然也可以在本地测试…

指针强制类型转换触发内存自动对齐

C语言的指针是我们操作很灵活&#xff0c;但是也留下了不少坑&#xff0c;今天工作遇到了一个指针的坑&#xff0c;这里复现一下&#xff1a; 指针类型强制转换,并进行解引用,引起的内存对齐问题.&#xff08;一&#xff09;问题复现&#xff1a; 运行环境&#xff1a;Ubuntu …

简单文本编辑器

一、前言 聚天地之灵气&#xff0c;集日月之精华&#xff01;一个简单的java文本编辑器由此而生。毕设所需&#xff0c;很是无奈&#xff01; 二、界面预览 三、实现思路 1.字体选择器的实现 (1).字体类 class MyFont{private Font font;private Color color;public Font getFo…

u-boot新增命令后出现data abort

&#xff08;一&#xff09;问题描述 u-boot下新增了一条update的命令&#xff0c;直接输入update没有报错&#xff0c;但是输入up按TAB键补全时发现出现data abort&#xff0c;而且输入不支持的命令也会有data abort &#xff08;二&#xff09;解决方法 最开始我包含的头…

sublime text学习

Ctrl / ---------------------注释 Ctrl 滚动 --------------字体变大/缩小 Ctrl N-------------------新建 软件右下角可以选择文档语法模式 Ctrl Shift P ------------------命令模式 命令&#xff1a; sshtml模糊匹配-----语法切换到html模式&#xff0c;同理所得&am…

core文件如何分析

目录(一&#xff09;什么是coredump(二)coredump产生的条件&#xff08;1&#xff09;coredump产生主要原因&#xff1a;&#xff08;2&#xff09;如何生成coredump(三&#xff09;gdb使用(四&#xff09;实例调试coredump文件(五&#xff09;总结(一&#xff09;什么是coredu…

SpringMVC+FreeMarker

前言&#xff1a; 最近在学习SpringMVC&#xff0c;模板引擎用的是FreeMarker&#xff0c;之前没有接触过。利用SpringMVC开发其实还有许多的步骤&#xff0c;比如控制层&#xff0c;服务层&#xff0c;持久化层&#xff0c;实体等等&#xff0c;先弄了一个小demo来总结一下Spr…

SpringMVC那点事

一、SpringMVC返回json数据的三种方式 1、第一种方式是spring2时代的产物&#xff0c;也就是每个json视图controller配置一个Jsoniew。 如&#xff1a;<bean id"defaultJsonView" class"org.springframework.web.servlet.view.json.MappingJacksonJsonView&q…

js学习内容的整理

1、jquery动态添加Table中的一行 function addTableRow(tableId){var html <tr>\......\</tr>";//行首插入一行if($(#tableId).find(tr).length 1){$(html).insertAfter($(#tableId).find(tr).eq(0));} else { $(html).insertBefore($(#tableId).find(tr).e…

(一)最邻近插值python实现

这里写目录标题&#xff08;一&#xff09;原始图像&#xff08;二&#xff09;最邻近插值实现&#xff08;三&#xff09;python实现1. 安装库2. python程序编写3. 效果4. 工程文件&#xff08;一&#xff09;原始图像 &#xff08;二&#xff09;最邻近插值实现 一般情况下我…

(二)双线性插值python实现

这里写目录标题&#xff08;一&#xff09;原始图像&#xff08;二&#xff09;双线性插值原理&#xff08;三&#xff09;python实现1. 安装库2. python程序编写3. 效果4. 工程文件&#xff08;一&#xff09;原始图像 &#xff08;二&#xff09;双线性插值原理 一般情况下我…

js self = this的解释

Demo 1: function Person(){this.name hjzgg;this.age 24;this.show function(){alert(name " " age);}}var p new Person();p.show(); 错误&#xff1a;name 和 age都没有定义。 Demo 2: function Person(){this.name hjzgg;this.age 24;this.show functio…