LINUX下重量級的命令strace使用介紹(原創)

來源:互聯網
上載者:User

LINUX下重量級的命令strace使用介紹(原創)
作者:餘超 Email:yuchao86@gmail.com

經常使用LINUX的朋友或許經常會疑問:linux是怎麼樣執行一條命令並得到正確輸出結果的呢?
比如你輸入一個pwd,得到的是當前路徑,輸入一個env顯示的是系統內容變數等等,
那你想知道他們是怎麼樣執行的嗎?
go ahead!!
首先:
我們先看下一個重量級的系統調用函數execve(),具體的參數和傳回值請大家使用man execve命令來查詢吧。
如下程式就是來自執行個體文檔:
[yuchao@yuchao-Latitude-E5410 scons]$cat yuexe.c 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main(int argc, char *argv[])
{
    char *newargv[] = { NULL, "hello", "world", NULL };
    char *newenviron[] = { NULL };

    if (argc != 2) {
    fprintf(stderr, "Usage: %s <file-to-exec>\n", argv[0]);
    exit(EXIT_FAILURE);
    }
    newargv[0] = argv[1];
    execve(argv[1], newargv, newenviron);
    perror("execve");   /* execve() only returns on error */
    exit(EXIT_FAILURE);
}
編譯成功後可以得到可執行檔:yuexe
[yuchao@yuchao-Latitude-E5410 scons]$ls
grap.c  Hello  helloscons.c  helloscons.o  helloSina.h  SConstruct  weibo.h  yuexe  yuexe.c  yuexe.o
查看命令yuexe執行Hello程式的核心調用過程如下:

[yuchao@yuchao-Latitude-E5410 scons]$sudo strace ./yuexe Hello 
[sudo] password for yuchao: 
execve("./yuexe", ["./yuexe", "Hello"], [/* 17 vars */]) = 0
brk(0)                                  = 0x84e3000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77b6000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=103314, ...}) = 0
mmap2(NULL, 103314, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb779c000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/libc.so.6", O_RDONLY)        = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0@n\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1421892, ...}) = 0
mmap2(NULL, 1427880, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x45f000
mmap2(0x5b6000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x157) = 0x5b6000
mmap2(0x5b9000, 10664, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x5b9000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb779b000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb779b6c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0x5b6000, 8192, PROT_READ)     = 0
mprotect(0x8049000, 4096, PROT_READ)    = 0
mprotect(0xd3f000, 4096, PROT_READ)     = 0
munmap(0xb779c000, 103314)              = 0
execve("Hello", ["Hello", "hello", "world"], [/* 0 vars */]) = 0
brk(0)                                  = 0x8cf0000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77fb000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=103314, ...}) = 0
mmap2(NULL, 103314, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb77e1000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/libc.so.6", O_RDONLY)        = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0@n\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1421892, ...}) = 0
mmap2(NULL, 1427880, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb3c000
mmap2(0xc93000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x157) = 0xc93000
mmap2(0xc96000, 10664, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xc96000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77e0000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb77e06c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xc93000, 8192, PROT_READ)     = 0
mprotect(0x8049000, 4096, PROT_READ)    = 0
mprotect(0xb1c000, 4096, PROT_READ)     = 0
munmap(0xb77e1000, 103314)              = 0
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 5), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77fa000
write(1, "Hell Scons,I'm YuChao\n", 22Hell Scons,I'm YuChao
) = 22
write(1, "Hello SINA,I'm YuChao\n", 22Hello SINA,I'm YuChao
) = 22
write(1, "Hell weibo,I'm YuChao\n", 22Hell weibo,I'm YuChao
) = 22
exit_group(0)                           = ?
[yuchao@yuchao-Latitude-E5410 scons]$
到這裡可以看得很清楚,美國系統調用的過程,由於linux核心不允許使用者態進程直接存取硬體資源,
當使用者進程需要訪問系統硬體資源時採用系統調用,美國系統調用都有調用參數和傳回值,
如果想瞭解系統調用的具體含義請man 之。。
如上可以看到:write(1,“Hell Scons,I'm YuChao\n",22 Hell Scons.....等等

另外,這個命令還可以用於最佳化系統網路時候使用,用於調用時候的效率考慮,用參數:strace -c ***可以看到具體的進程調用統計情況。
比如我查看我的本地web伺服器的啟動執行的核心調用過程:
$sudo strace -i -q -r -f -F -v -T -o strace_start strace /opt/lampp/lampp start
通過strace -c統計監控你的最佳化是否生效:
$sudo strace -c -o count_file /opt/lampp/lampp start

最後,當發生個http請求的時候,很多時候希望得到這個http請求發生了多少次資料庫SELECT操作,是否在同一個mysql connection串連裡面完成。
命令使用如下:
//-10321是mysqld的進程號,為了看到整條SQL語句,我們通過-s 1024希望輸出更多內容
#strace -f -F -ff -o strace-mysqld -s 1024 -p 10321
#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
... (這裡省去了一些)
通過如上的示範,你或許也看到了這個命令的厲害了,只能說linux是open的,你喜歡怎麼做就怎麼做,

不行你就去修改linux kernel來打造自己的版本吧,如果你再配合gdb來使用,就更high了。。



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.