systemtap是核心開發者必須要掌握的一個工具,本文我將簡單介紹一下此工具,後續將會有系列文章介紹systemtap的用法。
什麼是systemtap
假如現在有這麼一個需求:需要獲取正在執行的 Linux 系統的資訊,如我想知道系統什麼時候發生系統呼叫,發生的是什麼系統呼叫等這些資訊,有什麼解決方案呢?
- 最原始的方法是,找到核心系統呼叫的程式碼,加上我們需要獲得資訊的程式碼、重新編譯核心、安裝、選擇我們新編譯的核心重啟。這種做法對於核心開發人員簡直是夢魘,因為一遍做下來至少得需要1個多小時,不僅破壞了原有核心程式碼,而且如果換了一個需求又得重新做一遍上面的工作。所以,這種除錯核心的方法效率是極其底下的。
- 之後核心引入了一種Kprobe機制,可以用來動態地收集除錯和效能資訊的工具,是一種非破壞性的工具,使用者可以用它跟蹤執行中核心任何函式或執行的指令等。相比之前的做法已經有了質的提高了,但Kprobe並沒有提供一種易用的框架,使用者需要自己去寫模組,然後安裝,對使用者的要求還是蠻高的。
- systemtap 是利用Kprobe 提供的API來實現動態地監控和跟蹤執行中的Linux核心的工具,相比Kprobe,systemtap更加簡單,提供給使用者簡單的命令列介面,以及編寫核心指令的指令碼語言。對於開發人員,systemtap是一款難得的工具。
下面將會介紹systemtap的安裝、systemtap的工作原理以及幾個簡單的示例。
systemtap 的安裝
我的主機 Linux 發行版是32位 Ubuntu13.04,核心版本 3.8.0-30。由於 systemtap 執行需要核心的除錯資訊支撐,預設發行版的核心在配置時這些除錯開關沒有開啟,所以安裝完systemtap也是無法去探測核心資訊的。 下面我以兩種方式安裝並執行 systemtap:
方法一
- 編譯核心以支援systemtap
我們重新編譯核心讓其支援systemtap,首先你想讓核心中有除錯資訊,編譯核心時需要加上 -g 標誌;其次,你還需要在配置核心時將 Kprobe 和 debugfs 開關開啟。最終效果是,你能在核心 .config 檔案中看到下面四個選項是設定的:
1234CONFIG_DEBUG_INFOCONFIG_KPROBESCONFIG_DEBUG_FSCONFIG_RELAY
配置完之後,按照之前你編譯核心的步驟編譯即可。 - 獲取systemtap原始碼
從此地址 https://sourceware.org/systemtap/ftp/releases下載已經發布的systemtap的原始碼,截至目前(2013.9.17)最新版本為systemtap-2.3。下載完之後解壓。 當然你還可以使用 git 去克隆最新的版本(2.4),命令如下:
1git clone git://sources.redhat.com/git/systemtap.git - 編譯安裝systemtap
如果你下載的是最新版本的systemtap,那麼你需要新版的 elfutils,可以從https://fedorahosted.org/releases/e/l/elfutils/ 下載elfutils-0.156 版本。下載之後解壓縮到適合的目錄(我放在~/Document/ 下),不需要安裝,只要配置systemtap時指定其位置即可。 進入之前解壓systemtap的目錄,使用下面命令進行配置:
1./configure --with-elfutils=~/Document/elfutils-0.156
以這裡方法配置之後,你只需要再執行 make install 即完成systemtap的編譯安裝。如果需要解除安裝的話,執行 make uninstall。
方法二
由於發行版的核心預設無核心除錯資訊,所以我們還需要一個除錯核心映象,在http://ddebs.ubuntu.com/pool/main/l/linux/ 找到你的核心版本相對應的核心除錯映象(版本號包括後面的釋出次數、硬體體系等都必須一致),如針對我上面的核心版本,就可以用如下命令下載安裝核心除錯映象:
1 2 |
$ wget http://ddebs.ubuntu.com/pool/main/l/linux/linux-image-debug-3.8.0-30-generic_dbgsym_3.8.0-30.43_i386.ddeb $ sudo dpkg -i linux-image-debug-3.8.0-30-generic_dbgsym_3.8.0-30.43_i386.ddeb |
一般這種方法下,你只需要使用apt線上安裝systemtap即可:
1 |
$sudo apt-get install systemtap |
當然方法二僅限於Ubuntu發行版,至於其他的發行版並不能照搬,網上也有很多相關的資料。
systemtap 測試示例
安裝完systemtap之後,我們需要測試一下systemtap是否能正確執行:
示例一:列印hello systemtap
以root使用者或者具有sudo許可權的使用者執行以下命令:
1 |
$stap -ve 'probe begin { log("hello systemtap!") exit() }' |
如果安裝正確,會得到如下類似的輸出結果:
1 2 3 4 5 6 7 |
Pass 1: parsed user script and 96 library script(s) using 55100virt/26224res/2076shr/25172data kb, in 120usr/0sys/119real ms. Pass 2: analyzed script: 1 probe(s), 2 function(s), 0 embed(s), 0 global(s) using 55496virt/27016res/2172shr/25568data kb, in 0usr/0sys/4real ms. Pass 3: translated to C into "/tmp/stapYqNuF9/stap_e2d1c1c9962c809ee9477018c642b661_939_src.c" using 55624virt/27380res/2488shr/25696data kb, in 0usr/0sys/0real ms. Pass 4: compiled C into "stap_e2d1c1c9962c809ee9477018c642b661_939.ko" in 1230usr/160sys/1600real ms. Pass 5: starting run. hello systemtap! Pass 5: run completed in 0usr/10sys/332real ms. |
示例二:列印4s內所有open系統呼叫的資訊
建立systemtap指令碼檔案test2.stp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#!/usr/bin/stap probe begin { log("begin to probe") } probe syscall.open { printf ("%s(%d) open (%s)n", execname(), pid(), argstr) } probe timer.ms(4000) # after 4 seconds { exit () } probe end { log("end to probe") } |
將該指令碼新增可執行的許可權 chmod +x test2.stp
,使用./test2.stp
執行該指令碼,即可列印4s內所有open系統呼叫的資訊,列印格式為:程式名(程式號)開啟什麼檔案。 大家可以自行去測試,如果兩個示例都能正確執行,基本上算是安裝成功了!
systemtap 工作原理
systemtap 的核心思想是定義一個事件(event),以及給出處理該事件的控制程式碼(Handler)。當一個特定的事件發生時,核心執行該處理控制程式碼,就像快速呼叫一個子函式一樣,處理完之後恢復到核心原始狀態。這裡有兩個概念:
- 事件(Event):systemtap 定義了很多種事件,例如進入或退出某個核心函式、定時器時間到、整個systemtap會話啟動或退出等等。
- 控制程式碼(Handler):就是一些指令碼語句,描述了當事件發生時要完成的工作,通常是從事件的上下文提取資料,將它們存入內部變數中,或者列印出來。
Systemtap 工作原理是通過將指令碼語句翻譯成C語句,編譯成核心模組。模組載入之後,將所有探測的事件以鉤子的方式掛到核心上,當任何處理器上的某個事件發生時,相應鉤子上控制程式碼就會被執行。最後,當systemtap會話結束之後,鉤子從核心上取下,移除模組。整個過程用一個命令 stap
就可以完成。 上面只是簡單的原理,更多背後的機理參考網上資料和相應的論文。 圖 systemtap 處理流程
更多參考
- systemtap 官網給出了自學教程及相關論文,選擇看這個已經足夠了:https://sourceware.org/systemtap/documentation.html
- IBM 編寫的systemtap 指南也是很不錯的: http://www.redbooks.ibm.com/abstracts/redp4469.html