Linux调试分析--strace

版权声明:本文为博主原创文章,转载请注明出处-- https://blog.csdn.net/qq_38790716/article/details/85078379

1. 写在前面

在前面接触到了gdb这一有效的调试工具【linux】GDB调试,现在让我们来接触strace这一linux下的调试分析利器

首先我们知道gdb类似于我们常用的编程工具如vs、DEV中的debug,具有我们在那些编程工具中调试的所有功能;而strace与这一类的调试工具有很大的不同,strace是一个通过跟踪系统调用来让开发者知道一个程序在后台所做事情的工具

既然提到了系统调用,那就简单回顾一下系统调用。

  • 系统调用:为了创建文件、进程和复制文件等这些操作系统提供的服务,应用程序必须和操作系统进行交互。但应用程序无法直接访问linux内核。它既不能访问内核所占内存空间,也不能调用内核函数,不过,可以跳转到system_call的内核位置,内核会检查系统调用号,这个号码会告诉你内核进程正在请求哪种服务。然后,它查看系统调用表,找到所调用的内核函数地址,调用该函数,然后返回进程

    所有操作系统在其内核都有一些内建函数,这些函数可以用来完成一些系统级别的功能,一般称Linux系统上的这些函数为“系统调用

2. strace

2.1 几个常用strace操作

先做个简单的test:

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

编译运行得到可执行文件test,然后执行命令strace ./test:
在这里插入图片描述
在这里插入图片描述
每一行都是系统调用,等号左边是系统调用的函数及其参数,右边是该调用的返回值
strace 显示这些调用的参数并返回符号形式的值。strace 从内核接收信息,而且不需要以任何特殊的方式来构建内核。

下面简介几个常用的strace+参数分析

  1. 用strace来追踪信号传递
    还是以上述的程序,用strace ./test打开,然后另开一个窗口,输入killall test,意为杀死所有名为test的进程:
    在这里插入图片描述
    可以看到结果显示test进程"+++ killed by SIGTERM +++"

  2. 统计系统调用
    可以在strace后接一个参数-c得到进程所有的系统调用统计表,执行命令strace -c ./test
    在这里插入图片描述
    可看到程序调用哪些系统函数,调用次数、所耗时间及出错次数等信息,有助于分析程序运行速度瓶颈

  3. 获取每个系统调用花费的时间及每个系统调用被调用的时间

执行strace -T ./test得到每个系统调用花费的时间:
在这里插入图片描述
执行strace -t ./test得到每个系统调用发生的时间:
在这里插入图片描述

  1. 追踪某个进程,例:strace -p 21158:
    在这里插入图片描述

  2. 将strace输出写入文件
    例:将上述对test的strace调试写入到test.txt中,有下列两种方式:

strace -o test.txt ./test
strace -o ./test 2>test.txt  //与上述结果一致

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.2 用strace调试程序

一个简单的测试程序:

#include <iostream>
#include <fstream>
using namesapce std;
int main()
{
	ifstream in("test.txt");
	if (!in) {
		 cerr << " Can't open input file." << endl;
	     return -1;
    }
	return 0;
}

首先运行该程序得到结果:
在这里插入图片描述
发现输出异常,用strace调试:
在这里插入图片描述

在这里插入图片描述
发现异常是因为没有该文件导致的,查看目录:
在这里插入图片描述
并未test.txt,找到原因(这里只是举个简单的例子说明如何通过strace来分析程序)

2.3 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=3,5 
-e write=set 
输出写入到指定文件中的数据. 
-o filename 
将strace的输出写入文件filename 
-p pid 
跟踪指定的进程pid. 
-s strsize 
指定输出的字符串的最大长度.默认为32.文件名一直全部输出. 
-u username 
以username 的UID和GID执行被跟踪的命令

本文参考:Linux strace命令
Linux调试分析诊断利器——strace

---------------------------------------get------------------------------------------------------

1.又一linux调试分析工具
2.strace的基本操作

猜你喜欢

转载自blog.csdn.net/qq_38790716/article/details/85078379