使用strace监视系统调用

strace是一个必不可少的 调试工具,strace用来监视系统调用。

这个工具在系统负载非常高的时候,可以用来查看到底系统在做什么。

你可以了解到系统在用户态和内核态是如何通过系统调用和信号来实现程序的功能的.

安装

yum install strace -y

参数说明:
-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

strace常用来跟踪进程执行时的系统调用和所接收的信号。 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式,通 过系统调用访问硬件设备。strace可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间。

strace使用参数

-p    跟踪指定的进程

-f     跟踪由fork子进程系统调用

-F    尝试跟踪vfork子进程系统调吸入,与-f同时出现时, vfork不被跟踪

-o filename 默认strace将结果输出到stdout。通过-o可以将输出写入到filename文件中

-ff   常与-o选项一起使用,不同进程(子进程)产生的系统调用输出到filename.PID文件

-r     打印每一个系统调用的相对时间

-t     在输出中的每一行前加上时间信息。-tt 时间确定到微秒级。还可以使用-ttt打印相对时间

-v    输出所有系统调用。默认情况下,一些频繁调用的系统调用不会输出

-s     指定每一行输出字符串的长度,默认是32。文件名一直全部输出

-c    统计每种系统调用所执行的时间,调用次数,出错次数。

-e    expr 输出过滤器,通过表达式,可以过滤出掉你不想要输出

应用场景

#1.跟踪你的web服务器系统调用

系统调用优化,也是web性能优化的一个较为重要的方向,尤其是在I/O密集型web应用的情况。我们这里的测试环境是CentOS5.4+Nginx+FastCGI。

<?php

 

//file:hello.php

 

define

 

(

'DOCUMENT_ROOT'

,

 dirname

 

(

__FILE__

)

)

;

 

include

(

"hello.inc"

)

;

 

include

(

"./hello.inc"

)

;

 

include

(

DOCUMENT_ROOT .

 "/hello.inc"

)

;

 

?>

#strace -f -F -o strace_nginx strace /wwwchroot/nginx/sbin/nginx -c /wwwchroot/nginx/nginx.conf

... (有部分不重要的数据影响排版,在这里使用...代替)

//--接受来自客户端的http请求

4165  recv(16, "GET /hello.php HTTP/1.1\r\nHost: f"..., 32768, 0) = 391

4165  epoll_ctl(9, EPOLL_CTL_MOD, 16, {EPOLLIN|EPOLLOUT|EPOLLET, {u32=3081162952, u64=698098541354471624}}) = 0

//--进行DNS查找

4165  getsockname(16, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("222.73.211.214")}, [16]) = 0

//--新建一个socket,连接Fast-CGI,端口号为9000

4165  socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 17

4165  ioctl(17, FIONBIO, [1])           = 0

4165  epoll_ctl(9, EPOLL_CTL_ADD, 17, {EPOLLIN|EPOLLOUT|EPOLLET, {u32=3081163048, u64=697886249710965032}}) = 0

4165  connect(17, {sa_family=AF_INET, sin_port=htons(9000), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 )

4165  epoll_wait(9, {{EPOLLOUT, {u32=3081163048, u64=697886249710965032}}, {...}, 5\

12, 300000) = 2

4165  gettimeofday({1295420285, 130967}, NULL) = 0

4165  recv(16, 0xbfdd7d8b, 1, MSG_PEEK) = -1 EAGAIN (Resource temporarily unavailable)

4165  getsockopt(17, SOL_SOCKET, SO_ERROR, [0], [4]) = 0

//--将用户http请求交给Fast-CGI

4165  writev(17, [{"\1\1\0\1\0\10\0\0\0\1\0\0\0\0\0\0\1\4\0\1\3\30\0\0\21\7GATEWA"..., 832}], 1) = 832

4165  epoll_wait(9, {{EPOLLIN|EPOLLOUT, {u32=3081163048, u64=697886249710965032}}}, 512, 300000) = 1

4165  gettimeofday({1295420285, 131559}, NULL) = 0

//--接收Fast-CGI响应

4165  recv(17, "\1\6\0\1\0V\2\0X-Powered-By: PHP/5.2.10"..., 65536, 0) = 112

4165  readv(17, [{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 65424}], 1) = 0

4165  mmap2(NULL, 274432, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7514000

4165  close(17)                         = 0

4165  munmap(0xb7514000, 274432)        = 0

//-- 响应客户端http请求,即http响应

4165  writev(16, [{"HTTP/1.1 200 OK\r\nServer: nginx/0"..., 228}, {"22\r\n", 4}, ..., 5) = 273

4165  write(5, "116.66.34.82 - - [19/Jan/2011:14"..., 191) = 191

4165  setsockopt(16, SOL_TCP, TCP_NODELAY, [1], 4) = 0

4165  recv(16, 0x9b024e8, 32768, 0)     = -1 EAGAIN (Resource temporarily unavailable)

...

通过这些,我们只能够大概地了解,Nginx这里启用了epoll。同时,还可以了解到Nginx和Fast-CGI底层是如何运作的。奇 怪,hello.php文件中有三个inclue,即加载了三次文件,这里没有看到相应的i/o逻辑操作,是为什么呢?这是因为,Nginx并没解析处理PHP脚本,而是交给Fast-CGI去做这部事情了。

#strace -f -F -o php-cgi-strace /wwwchroot/php/bin/php-cgi --fpm-config /wwwchroot/php/etc/php-fpm.conf

//--接收来自Nginx发出的请求

4510  <... accept resumed> {sa_family=AF_INET, sin_port=htons(35983), sin_addr=inet_addr("127.0.0.1")}, [16]) = 3

4510  clock_gettime(CLOCK_MONOTONIC, {22638545, 869965681}) = 0

4510  poll([{fd=3, events=POLLIN}], 1, 5000) = 1 ([{fd=3, revents=POLLIN}])

4510  read(3, "\1\1\0\1\0\10\0\0", 8)   = 8

4510  read(3, "\0\1\0\0\0\0\0\0", 8)    = 8

4510  read(3, "\1\4\0\1\0035\3\0", 8)   = 8

4510  read(3, "\21\7GATEWAY_INTERFACECGI/1.1\17\5SERV"..., 824) = 824

4510  read(3, "\1\4\0\1\0\0\0\0", 8)    = 8

4510  time(NULL)                        = 1295425149

//--加载请求资源文件hello.php

4510  lstat64("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0

4510  lstat64("/var/www", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0

4510  lstat64("/var/www/ep", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0

4510  lstat64("/var/www/ep/hello.php", {st_mode=S_IFREG|0644, st_size=119, ...}) = 0

4510  clock_gettime(CLOCK_MONOTONIC, {22638545, 870893872}) = 0

4510  setitimer(ITIMER_PROF, {it_interval={0, 0}, itvalue={60, 0}}, NULL) = 0

4510  rt_sigaction(SIGPROF, {0x835c120, [PROF], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0

4510  rt_sigprocmask(SIG_UNBLOCK, [PROF], NULL, 8) = 0

4510  time(NULL)                        = 1295425149

4510  open("/var/www/ep/hello.php", O_RDONLY) = 4

4510  fstat64(4, {st_mode=S_IFREG|0644, st_size=119, ...}) = 0

4510  time(NULL)                        = 1295425149

4510  chdir("/var/www/ep")              = 0

4510  fstat64(4, {st_mode=S_IFREG|0644, st_size=119, ...}) = 0

4510  mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fe7000

4510  read(4, "\n", 8192) = 29

4510  read(4, "", 8192)                 = 0

4510  read(4, "", 8192)                 = 0

4510  close(4)                          = 0

//--  加载hello.inc, 对应php代码include './hello.inc'

4510  getcwd("/var/www/ep"..., 4096)    = 12

4510  time(NULL)                        = 1295425149

4510  open("/var/www/ep/hello.inc", O_RDONLY) = 4

4510  fstat64(4, {st_mode=S_IFREG|0644, st_size=29, ...}) = 0

4510  read(4, "\n", 8192) = 29

4510  read(4, "", 8192)                 = 0

4510  read(4, "", 8192)                 = 0

4510  close(4)                          = 0

4510  time(NULL)                        = 1295425149

//-- 加载hello.inc, 对应php代码include DOCUMENT_ROOT . '/hello.inc'

4510  lstat64("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0

4510  lstat64("/var/www", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0

4510  lstat64("/var/www/ep", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0

4510  lstat64("/var/www/ep/hello.inc", {st_mode=S_IFREG|0644, st_size=29, ...}) = 0

4510  open("/var/www/ep/hello.inc", O_RDONLY) = 4

4510  fstat64(4, {st_mode=S_IFREG|0644, st_size=29, ...}) = 0

4510  read(4, "\n", 8192) = 29

4510  read(4, "", 8192)                 = 0

4510  read(4, "", 8192)                 = 0

4510  close(4)                          = 0

//-- 将响结果输出给Nginx,并且关闭连接

4510  write(3, "\1\6\0\1\0V\2\0X-Powered-By: PHP/5.2.10"..., 96) = 96

4510  setitimer(ITIMER_PROF, {it_interval={0, 0}, itvalue={0, 0}}, NULL) = 0

4510  write(3, "\1\3\0\1\0\10\0\0\0\0\0\0\0ere", 16) = 16

4510  shutdown(3, 1 /* send */)         = 0

4510  recv(3, "\1\5\0\1\0\0\0\0", 8, 0) = 8

4510  recv(3, "", 8, 0)                 = 0

4510  close(3)                          = 0

通过跟踪php-cgi,我们可以知道,相较与其它二种方法include ‘./hello.inc’的性能是最高的。这里看到strace输出都被截断了,如果你需要看到更多的输出,可以通过-s选项,让strace输出更多内容。

当你发现某个http请求造成CPU占用效骤然升高,你可以通过strace跟踪查找问题的根源。同时,你也可以通过strace -c统计监控你的优化是否生效

#2. MySQL执行语句列表

当发生个http请求的时候,很多时候希望得到这个http请求发生了多少次数据库SELECT操作,是否在同一个mysql connection连接里面完成。这里以访问本页为例子,通过strace来跟踪这些MySQL SELECT查询语句。

//-9514是mysqld的进程号,为了看到整条SQL语句,我们通过-s 1024希望输出更多内容

#strace -f -F -ff -o strace-mysqld -s 1024 -p 9514

#find . -name "strace-mysqld*" -type f -print |xargs grep -n "SELECT.*FROM wp_"

./strace-mysqld.19203:64:

read(19, "\3SELECT option_name, option_value FROM wp_options WHERE autoload = 'yes'", 72) = 72

./strace-mysqld.19203:165:

read(19, "\3SELECT * FROM wp_users WHERE user_login = 'admin'", 50) = 50

./strace-mysqld.19203:184:

read(19, "\3SELECT meta_key, meta_value FROM wp_usermeta WHERE user_id = 1", 63) = 63

./strace-mysqld.19203:295:

read(19, "\3SELECT option_value FROM wp_options WHERE option_name = 'rewrite_rules' LIMIT 1", 80) = 80

./strace-mysqld.19203:311:

read(19, "\3 SELECT   wp_posts.* FROM wp_posts  WHERE 1=1  AND wp_posts.ID = 501

     AND wp_posts.post_type = 'post'  ORDER BY wp_posts.post_date DESC ", 136) = 136

... (这里省去了一些)

其他

strace远不止这么强大,你可以善用之,我想你会离不开它的。同时,你还可以联合gdb和ltrace,你的工作会更加高效。

linux的strace命令案例分析



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值