shell学习五十四天----进程系统调用的追踪strace

strace

前言:strace常用来跟踪进程执行时的系统调用的所接受的信号.linux世界,进程是不能直接访问硬件设备,当进程需要访问硬件(比如读取磁盘文件,接收网络数据等等),必须由用户态模式切换至内核态模式,通过系统调用访问硬件设备.strace可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间,有其在调试的时候,strace能帮助你追踪到一个程序所执行的系统调用.当你想知道程序和操作系统是如何交互的时候,这是极其方便的,比如你想知道执行了哪些系统调用,并且以何种顺序执行.

 

 

strace详解

格式:

strace [ -dffhiqrtttTvxx ] [ -acolumn ] [ -eexpr ] ... [ -ofile ] [-ppid ] ... [ -sstrsize ] [ -uusername ] [ -Evar=val ] ... [ -Evar ]... [ command [ arg ... ] ] 

 

 

strace -c [ -eexpr ] ... [ -Ooverhead ] [ -Ssortby ] [ command [ arg... ] ]

选项:

选项名

说明

-f ,-F

告诉strace同时跟踪forkvfork出来的信号

-o(字母)xxxx.txt

输出到某个文档

-e execve

只记录execve这类系统调用.

 

案例:

首先使用vim编写一个C语言的程序,代码如下:

#filename test.c

#include 

int main()

{

int a;

scanf(“%d”,&a);

printf(“%09d\n”,a);

return 0;

}

然后使用命令:#gcc -o test test.c,这样会得到一个可执行的文件.

我们执行这个可执行文件(先不使用strace):#./test

执行期间这个程序会要求我们输入一个整数,我们输入99,会得到以下结果:000000099

接着我们使用strace:#strace ./test

输出很多,我就不复制,我一看这个输出的是我想到了黑客帝国这部电影,我第一次看的时候差不多就是这样...当时觉得好炫酷,不过看见我自己电脑上的这一坨,你够了,我不想看到你!

输出的这一些内容称为stracetrace结构,trace结构可以看到,系统首先调用execve开始一个新的进程,接着进行环境的初始化操作,最后停顿在”read(0,”上面,这就是执行到了我们的scanf函数,等待我们输入数字,在输入完99之后,在调用write函数将格式化后的数值”000000099”输出到屏幕上,最后掉用wxit_group退出进行,完成整个程序的执行过程.

 

跟踪信号传递.

 

我们还是使用上面那个编译好的test程序,来观察进程接收信号的情况.还是先:#strace ./test,等到等待输入的画面的时候不要输入任何东西,然后打开另一个窗口,输入如下命令:

#killall test

这个时候我们就能看到我们的test程序退出了,最后的trace结果的最后两行:

--- SIGTERM (Terminated) @ 0 (0) ---

+++ killed by SIGTERM +++

trace中很清楚的告诉你test进程”+++ killed by SIGTERM +++”,其中SIGTERM信号为程序结束信号,SIGKILL不同的是该信号可以被阻塞和处理.通常用来要求程序自己正常退出.shell命令kill缺省产生SIGTERM.

 

 

系统调用统计

strace不光能追踪系统调用,通过使用-c选项,它还能江金城所有的系统调用做一个统计分析给你,案例如下:

#strace -c ./test(需要按下Ctrl+C)

% time     seconds  usecs/call     calls    errors syscall

------ ----------- ----------- --------- --------- ----------------

  -nan    0.000000           0         2           read

  -nan    0.000000           0         1           write

  -nan    0.000000           0         2           open

  -nan    0.000000           0         2           close

  -nan    0.000000           0         4           fstat

  -nan    0.000000           0        10           mmap

  -nan    0.000000           0         3           mprotect

  -nan    0.000000           0         1           munmap

  -nan    0.000000           0         1           brk

  -nan    0.000000           0         1         1 access

  -nan    0.000000           0         1           execve

  -nan    0.000000           0         1           arch_prctl

------ ----------- ----------- --------- --------- ----------------

100.00    0.000000                    29         1 total

 

-c选项的含义是统计每一系统调用的所执行的时间,次数和出错的次数等.

 

 

 

常用参数说明

除了-c参数之外,strace还提供了其他有用的参数给我们,让我们方便的得到自己想要的信息,介绍如下:

重定向输出:

参数-o用在将strace的结果输出到文件中,如果不指定-o参数的话,默认的输出设备是STDERR,也就是说使用”-o filename”和”2>filename”的结果是一样的.

以下这两个命令都是讲strace结果输出到文件test.txt

#strace -c -o test.txt ./test

#strace -c ./test 2>test.txt

对系统调用进行计时

strace可以使用参数-T将每个系统调用所花费的事件打印出来,每个掉用的时间花销现在在调用行最右边的尖括号里面.

read(0, 1

"1\n", 1024)                    = 2 <7.195016>

fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0 <0.000010>

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f1431bd1000 <0.000014>

write(1, "000000001\n", 10000000001

)             = 10 <0.000011>

exit_group(0)                           = ?

 

表示看不懂,不懂得东西,现在不要深究.

 

 

系统调用的时间

这是一个很有用的功能,strace会将每次系统调用的发生时间记录下来,只要使用-t/tt/ttt三个参数就可以看到效果了,具体案例如下:

参数名

输出样式

说明

-t

10:50:10 exit_group(0)

输出结果精确到秒

-tt

 

10:50:48.463555 exit_group(0)

输出结果精确到微秒

-ttt

1438138307.923671 exit_group(0)

精确到微妙,而且时间表示为unix时间戳

 

 

截断输出

-s参数用于指定trsce结果的每一行输出的字符串的长度,下面看看test程序中-s参数对结果有什么影响,现指定-s10,然后在read的地方输入一个超过10个字符的字符串:

#strace -s 10 ./test

read(0, 123456789011

"1234567890"..., 1024)          = 13

部分输出结果

分析:我们一共输入了12个字符,而我们看到的结果只有10

 

 

trace一个现有的进程

strace不光能自己初始化一个进程进行trace,还能追踪现有的进程,参数-p就是去的这个用法,用法简单,具体如下:

#strace -p pid   //跟踪指定的进程PID

 

 

 

 


你可能感兴趣的:(shell脚本编程)