Linux下,进程不能直接访问硬件设备。当进程需要访问硬件设备时(读取磁盘文件、接收网络数据等),则必须由用户态切换为内核态,然后通过系统调用来访问硬件设备。strace是跟踪进程执行时的系统调用和所接收的信号(即它跟踪到一个进程产生的系统调用,包括参数、返回值、执行消耗的时间)。strace最简单的用法是执行一个指定的命令(过程中,starce会记录和解析命令进程的所有系统调用及这个进程的所有的信号值),在指定命令结束后立即退出。

1、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=3,5 -e write=set 输出写入到指定文件中的数据.

-o filename 将strace的输出写入文件filename

-p pid 跟踪指定的进程pid.

-s strsize 指定输出的字符串的最大长度.默认为32.文件名一直全部输出.

-u username 以username的UID和GID执行被跟踪的命令

2、strace的使用实例

对于如下test.cpp程序

#include<iostream>
using namespace std;
int main(){int a;cin>>a;cout<<a<<endl;return 0;
}

g++ -o test test.cpp进行编译。

(1)直接运行结果如下:

(2)strace追踪系统调用(strace ./test),结果如下:

[root@init1 strace]# strace ./test
execve("./test", ["./test"], [/* 25 vars */]) = 0
brk(NULL)                               = 0x1ec7000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd40f43f000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=29479, ...}) = 0
mmap(NULL, 29479, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fd40f437000
close(3)                                = 0
open("/lib64/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 \262\5\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=991616, ...}) = 0
mmap(NULL, 3171168, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fd40ef18000
mprotect(0x7fd40f001000, 2093056, PROT_NONE) = 0
mmap(0x7fd40f200000, 40960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xe8000) = 0x7fd40f200000
mmap(0x7fd40f20a000, 82784, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fd40f20a000
close(3)                                = 0
open("/lib64/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0pS\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1139680, ...}) = 0
mmap(NULL, 3150136, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fd40ec16000
mprotect(0x7fd40ed17000, 2093056, PROT_NONE) = 0
mmap(0x7fd40ef16000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x100000) = 0x7fd40ef16000
close(3)                                = 0
open("/lib64/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220*\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=88776, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd40f436000
mmap(NULL, 2184192, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fd40ea00000
mprotect(0x7fd40ea15000, 2093056, PROT_NONE) = 0
mmap(0x7fd40ec14000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x14000) = 0x7fd40ec14000
close(3)                                = 0
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P%\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2173512, ...}) = 0
mmap(NULL, 3981792, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fd40e633000
mprotect(0x7fd40e7f6000, 2093056, PROT_NONE) = 0
mmap(0x7fd40e9f5000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c2000) = 0x7fd40e9f5000
mmap(0x7fd40e9fb000, 16864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fd40e9fb000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd40f435000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd40f433000
arch_prctl(ARCH_SET_FS, 0x7fd40f433740) = 0
mprotect(0x7fd40e9f5000, 16384, PROT_READ) = 0
mprotect(0x7fd40ec14000, 4096, PROT_READ) = 0
mprotect(0x7fd40ef16000, 4096, PROT_READ) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd40f432000
mprotect(0x7fd40f200000, 32768, PROT_READ) = 0
mprotect(0x600000, 4096, PROT_READ)     = 0
mprotect(0x7fd40f440000, 4096, PROT_READ) = 0
munmap(0x7fd40f437000, 29479)           = 0
fstat(0, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd40f43e000
read(0, 123456
"123456\n", 1024)               = 7
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd40f43d000
write(1, "123456\n", 7123456
)                 = 7
exit_group(0)                           = ?
+++ exited with 0 +++

注:以上每一行都是一条系统调用,等号左边是系统调用的函数名和参数,右边是该调用的返回值

strace显示这些调用的参数并返回符号形式的值。

strace从内核接收信息,而且不需要以任何特殊的方式来构建内核

(3)strace跟踪信号传递

首先,strace ./test,等到等待输入的那一步时,不输入任何东西,然后打开另外一个窗口,输入命令:killall test

我们观察第一次打开的strace窗口中,此时,我们看见程序退出了,结果如下(仅截取末尾几行):

(4)系统调用统计

1)使用-c参数,它会将进程的所有系统调用做一个统计分析展示出来

这里清楚的告诉我们,在这一过程中调用了哪些系统函数,调用了多少次,消耗了多少时间等信息,这对我们分析一个程序是很有帮助的。实例如下:

2)-o选项重定向输出

-o 将strace 的结果输出到文件中若不指定 -o 参数的话,默认的输出设备是STDERR,也就是说,使用 -o filename 和 2>filename 的结果是一样的。执行strace -c -o file ./test结果如下:

3)-T选项对系统调用进行计时

-T 将每个系统调用所花费的时间打印出来。每个调用的花销体现在调用行最右边的尖括号里边(下面只是调用的一部分)

strace -T ./test执行后结果如下(截取前几行):

4)系统调用的时间

-t/-tt/-ttt

-t 精确到秒

-tt  精确到微秒

-ttt  精确到微秒,而且时间表示为unix时间戳。

调用strace -t ./test 结果如下(截取前几行):

5)截断输出

-s 指定trace结果的每一行输出的字符串长度

现指定-s 5,而在read时,我们输入一个超过5个字符的字符串

6)追踪现有的进程

-p pid

(5)用strace调试程序

对于如下程序:

#include<iostream>
#include <fstream>
#include <stdlib.h>using namespace std;int main(){char buffer[256];ifstream in("input.txt");if(!in.is_open()){cout<<"error open file"<<endl;exit(1);}while(!in.eof()){in.getline(buffer,100);cout<<buffer<<endl;}return 0;
}

如果不创建input.txt文件夹的话直接执行肯定会报错,如下:

但是仅仅看这个提示我并不知道究竟是哪个系统调用出错,或者说我想更精确的定位出错的位置要怎么办?

执行strace ./stracetest后就能够直接定位具体的错误位置了:

strace的简单用法相关推荐

  1. 反编译工具jad简单用法

    反编译工具jad简单用法 下载地址: [url]http://58.251.57.206/down1?cid=B99584EFA6154A13E5C0B273C3876BD4CC8CE672& ...

  2. QCustomPlot的简单用法总结

    QCustomPlot的简单用法总结 第一部分:QCustomPlot的下载与安装 第二部分:QCustomPlot在VS2013+QT下的使用 QCustomPlot的简单用法总结    写在前面, ...

  3. python matplotlib 简单用法

    python matplotlib 简单用法 具体内容请参考官网 代码 import matplotlib.pyplot as plt import numpy as np # 支持中文 plt.rc ...

  4. Windump网络命令的简单用法

    Windump网络命令的简单用法 大家都知道,unix系统下有个tcpdump的抓包工具,非常好用,是做troubleshooting的好帮手.其实在windows下也有一个类似的工作,叫windum ...

  5. Android TabLayout(选项卡布局)简单用法实例分析

    本文实例讲述了Android TabLayout(选项卡布局)简单用法.分享给大家供大家参考,具体如下: 我们在应用viewpager的时候,经常会使用TabPageIndicator来与其配合.达到 ...

  6. shell expect的简单用法

    为什么需要expect?     我们通过Shell可以实现简单的控制流功能,如:循环.判断等.但是对于需要交互的场合则必须通过人工来干预,有时候我们可能会需要实现和交互程序如 telnet服务器等进 ...

  7. Shellz中awk的简单用法

    其实shell脚本的功能常常被低估.在实际应用中awk sed 等用法可以为shell提供更为强大的功能.下面我们将一下awk调用的简单方法进行了总结.方便同学们学习: awk的简单用法: 第一种调用 ...

  8. python装饰器实例-Python装饰器原理与简单用法实例分析

    本文实例讲述了Python装饰器原理与简单用法.分享给大家供大家参考,具体如下: 今天整理装饰器,内嵌的装饰器.让装饰器带参数等多种形式,非常复杂,让人头疼不已.但是突然间发现了装饰器的奥秘,原来如此 ...

  9. python装饰器实例-Python装饰器简单用法实例小结

    本文总结分析了Python装饰器简单用法.分享给大家供大家参考,具体如下: 装饰器在python中扮演着很重要的作用,例如插入日志等,装饰器可以为添加额外的功能同时又不影响业务函数的功能. 比如,运行 ...

  10. 【Android 应用开发】Google 官方 EasyPermissions 权限申请库 ( 最简单用法 | 一行代码搞定权限申请 | 推荐用法 )

    文章目录 一.添加依赖 二.在 AndroidManifest.xml 中配置权限 三.权限申请最简单用法 四.推荐使用的用法 五.GitHub 地址 上一篇博客 [Android 应用开发]Goog ...

最新文章

  1. 如何利用输入输出流往文件中不断添加内容
  2. python怎么学最快-python怎么快速自学?
  3. 4.3.6 无分类编址CIDR(构成超网)
  4. Android应用开发--MP3音乐播放器代码实现(二)
  5. 【ORACLE 高可用】使用GOLDENGATE 配置Oracle-MySQL的异构复制
  6. Unity SRP自定义渲染管线 -- 5.Directional Shadows
  7. 软件项目管理第一课—IT项目管理实战案例介绍
  8. 如何在 Windows 2000 中安装 Microsoft 环回适配器
  9. ubuntu 12.04(64位)下搭建android5.0开发环境 (win7 虚拟机)
  10. 问题六十五:二叉查找树的一个应用实例——求解一元十次方程时单实根区间的划分
  11. DevOps使用教程 华为云(7)团队绩效评估 工时统计
  12. 32位电脑ODBC连接
  13. RapidMiner介绍与实践(三)K-Means
  14. 微软大中华区迎来10年来首位华人CEO;华为前高管出任云南白药CEO;港交所新行政总裁委任获批 | 高管变动...
  15. Inno Setup打包添加和去除管理员权限
  16. 主题美化 —— IAR篇
  17. Java: 实训三 类与对象、继承
  18. VBA Excel 直接增加任意名字sheet
  19. 解决HbuildX无法格式化TS文件的问题
  20. 使用支付宝实现零手续费跨行转帐。

热门文章

  1. mysql 大小限制_MYSQL 表大小限制
  2. 蓝桥杯2018年第九届C/C++省赛B组第一题-第几天
  3. git临时保存git stash命令
  4. Java50道经典习题-程序7 处理字符串
  5. iOS socket 通讯 客户端和服务端(CocoaAsyncSocket 的用法)
  6. 关于BSTR数据类型
  7. windows下使用Wireshark调试chrome浏览器的HTTP/2流量
  8. JQuery------jQuery.parseHTML()的使用方法
  9. gtest简短,简单易用
  10. hibernate防止sql注入(转载)