哈哈哈,看到標題是不是以爲strace是編程語言呢?不是啦,小鎮爲了學習strace足足準備了一個多星期,而這次終於是吧strace的文章放了出來,哎,怎麼說呢,strace出來的還是有相當多的函數看不太懂,不過這次咱這次就來個strace的入門,簡稱strace之helloworld。
strace是一個有用的小工具 – 大多數Linux系統默認已經安裝 – 可以通過跟蹤系統調用來讓你知道一個程序在後臺所做的事情。Strace是一個基礎的調試工具;但是即便你不是在跟蹤一個問題的時候它也是一個極好的軟件。它能告訴你很多關於一個Linux程序怎樣工作的信息。
我們這次用c語言寫了一個helloworld的程序,然後編譯完之後去strace,讓我們看看一個基本的helloworld經過了哪些系統調用。首先編譯:gcc -o helloworld helloworld.c 然後執行命令strace ./helloworld。最後彈出strace出來的內容。好了,在這裏給大家截張圖吧。如下圖所示:
下面我們來一行一行的去解釋:
第一行:execve("./helloworld", ["./helloworld"], [/* 28 vars */]) = 0
我們前面有一篇博文是關於linux的execve函數的,大家可以調出來看看,方便學習。execve是linux執行命令的函數,第一個參數./helloworld是命令的所在路徑,很明顯路徑就是本目錄下的helloworld,然後第二個是命令的集合,命令本身也是./helloworld並且不帶參數,第三個參數是環境變量集,這個大家不用管。
第二行:brk(0)
brk是c庫函數而不是系統調用,一般來說系統調用通常是提供了最小最基本的功能,而庫函數通常提供比較複雜的功能,brk是從堆中分配空間,本質是移動一個位置,向後移就是分配空間,向前移就是釋放空間,而brk(0)是用來返回比較精確的虛擬內存的使用情況,在這裏可以理解爲內核需要詳細瞭解虛擬空間的使用情況。
第三行&第四行:mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b0ebc632000
這邊的mmap大家可以看到參數是flag參數是MAP_ANONYMOUS,然後fd文件描述符是-1,證明這個mmap是一個匿名映射,也就是說建立一個沒有與文件映射的映射區,這邊與第四行的作用咱們不得而知。因爲具體的代碼的運作我們是看不出來的。strace只是看到了系統調用而已,不過這對我們理解這次的strace一點關係都沒有。
第五行:access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
還記得我以前寫的一個關於教你做黑客的文章麼,這裏的ld.so.preload就是用來預加載共享庫的環境變量的文件。不過這裏我們沒有用來預加載的共享庫,所以自然返回的是No suck file or directory了。
第六行:open("/etc/ld.so.cache", O_RDONLY) = 3
然後我們需要打開動態鏈接庫的加載緩存文件,打開後返回值爲3的文件描述符。
第七行:fstat(3, {st_mode=S_IFREG|0644, st_size=94316, ...}) = 0
獲取該文件描述符所指向文件的狀態和屬性,就是剛剛的動態鏈接庫的加載緩存文件的文件狀態。
第八行:mmap(NULL, 94316, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2b0ebc634000
將這個緩存文件映射到虛擬內存中,恩,這個94316的大小就是用過fstat獲取到的。
第九行:close(3)
將該文件描述符關閉。
第十行到第十七行:同樣是一系列的操作,知不過就是操作的從ld.so.cache中讀到的libc.so.6文件,並且讀入ld.so.cache中的內容:
十八行到二十二行:對內存的一系列的操作,這邊的操作只能看看表面的意思,具體在幹嘛誰知道呢?
第二十三行:fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
獲取標準輸出文件描述符的狀態
第二十五行:write(1, "Helloworld\n", 11) = 11
將Helloworld寫入到標準輸出的文件中去。最後通過exit_group終止線程組,大家可以看到,知識量是很大的,如果想完全的看懂strace的過程,基本上要對linux的內核函數有非常深入的理解纔行,所以向我們這種運維才需要用到strace的網絡安全工程師來說,大概適度的瞭解是最好的。