http://sourceware.org/systemtap/
https://sourceware.org/systemtap/wiki
https://sourceware.org/systemtap/documentation.html
https://www.cnblogs.com/hazir/p/systemtap_introduction.html (推薦)
https://vcpu.me/systemtap-skills/
http://www.redbooks.ibm.com/abstracts/redp4469.html
https://segmentfault.com/a/1190000010774974
https://www.cnblogs.com/hazir/p/systemtap_introduction.html
1、安裝
Ubuntu
sudo apt-get install systemtap(不建議這麼玩,Ubuntu自帶的經常有問題)
centos
yum install systemtap systemtap-runtime
也可以通過源碼進行安裝,下載地址:https://sourceware.org/systemtap/ftp/releases/ 。解壓然後進入根目錄,執行如下命令:
tar -zxvf systemtap-4.1.tar.gz
cd systemtap-4.1/
./configure --prefix=/目錄(期望安裝的目錄)
make
sudo make install
執行配置是可能遇到各種庫找不到,缺啥補啥,常見的庫是下面這些:
sudo apt-get install elfutils
sudo apt-get install libncurses5-dev
sudo apt-get install flex
sudo apt-get install bison
sudo apt-get install gettext
sudo apt-get install libdw-dev
sudo apt-get install g++
2、安裝調試需要debug
首先由於Systemtap運行時需要內核的調試信息支撐,默認發行版的內核在配置時,這些調試開關是關閉的,所以爲了Systemtap能夠正常運行,我們首先要使內核開啓運行調試信息功能。主要有兩種方法:
方法一:下載並安裝debuginfo安裝包
由於發行版的內核默認無內核調試信息,所以我們還需要一個調試內核鏡像,在http://ddebs.ubuntu.com/pool/main/l/linux/ 找到你的內核版本相對應的內核調試鏡像(版本號包括後面的發佈次數、硬件體系等都必須一致),
假設我的內核版本2.6.32-24,i386結構,那麼我需要下載
linux-image-2.6.32-24-generic-dbgsym_2.6.32-24.42_i386.ddeb下載後安裝
dpkg -i linux-image-2.6.32-24-generic-dbgsym_2.6.32-24.42_i386.ddeb
方法二:重新編譯內核
參考:https://blog.csdn.net/linjiasen/article/details/89850357
1.git下載最新的內核源碼
git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
或者更快的: git clone https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux.git
2 配置kernel
make memuconfig打開
General Setup -- ->
[*] Kernel->user space relay support (formerly relayfs)
[*] Kprobes
kernel hacking -- ->
[*]Kernel debugging
[*]Compile the kernel with debug info
[*]Debug Filesystem
然後查看.config下面debug信息是否打開
CONFIG_DEBUG_INFO
CONFIG_KPROBES
CONFIG_RELAY
CONFIG_DEBUG_FS
CONFIG_MODULES
CONFIG_MODULE_UNLOAD
CONFIG_UPROBES 或者CONFIG_UTRACE
3、測試是否安裝成功
如果pass1-5都沒有錯誤,說明systemtap安裝成功了。
stap -ve 'probe kernel.function("_do_fork") { print("hello world\n") exit() }'
stap -ve 'probe begin { log("hello Systemtap!") exit() }'
stap -ve 'probe begin { log("hello Systemtap!") exit() }'
Pass 1: parsed user script and 476 library scripts using 116624virt/86344res/5540shr/81212data kb, in 280usr/40sys/331real ms.
Pass 2: analyzed script: 1 probe, 2 functions, 0 embeds, 0 globals using 118208virt/88052res/5676shr/82796data kb, in 10usr/0sys/9real ms.
Pass 3: using cached /root/.systemtap/cache/d0/stap_d06faf54f2557de2112cfd40af92ad47_1150.c
Pass 4: using cached /root/.systemtap/cache/d0/stap_d06faf54f2557de2112cfd40af92ad47_1150.ko
Pass 5: starting run.
WARNING: module version mismatch (#1 SMP Tue May 12 20:00:21 CST 2020 vs #1 SMP Tue May 12 16:41:02 CST 2020), release 5.3.0-rc7
hello Systemtap!
Pass 5: run completed in 0usr/10sys/455real ms.
上面打印的pass1-5就是對應SystemTap的處理流程有5個步驟:解析script文件(parse)、細化(elaborate)、script文件翻譯成C語言代碼(translate)、編譯C語言代碼(生成內核模塊)(build)、加載內核模塊(run)。
systemtap 的核心思想是定義一個事件(event),以及給出處理該事件的句柄(Handler)。當一個特定的事件發生時,內核運行該處理句柄,就像快速調用一個子函數一樣,處理完之後恢復到內核原始狀態。這裏有兩個概念:
- 事件(Event):systemtap 定義了很多種事件,例如進入或退出某個內核函數、定時器時間到、整個systemtap會話啓動或退出等等。
- 句柄(Handler):就是一些腳本語句,描述了當事件發生時要完成的工作,通常是從事件的上下文提取數據,將它們存入內部變量中,或者打印出來。
evnet有很多種:進入和退出一個function,timer爆發,systemtap的開始和停止。
handler:腳本語言,當event發生時工作。
同步事件包括:
syscall.system_call
vfs.file_operation
kernel.function("function")
kernel.trace("tracepoint")
module("module").function("function")
異步事件包括:
begin
end
timer events
printf
Systemtap 工作原理是通過:將腳本語句翻譯成C語句(Pass1 -3:parse-translate),編譯成內核模塊(Pass4:compile)。模塊加載之後,將所有探測的事件以鉤子的方式掛到內核上(load),當任何處理器上的某個事件發生時,相應鉤子上句柄就會被執行(run)。最後,當systemtap會話結束之後,鉤子從內核上取下,移除模塊。整個過程用一個命令 stap
就可以完成。
4、使用
(1) stap
通常直接使用stap執行用SystemTap語法編寫的腳本即可。
stap - systemtap script translator/driver
stap test.stp // .stp後綴的文件是用SystemTap語法編寫的腳本
probe begin
{
print ("hello world\n")
exit ()
}
probe end
{
print ("Bye\n")
}
上面腳本保存成hello_world.stp,然後stap -v hello_world.stp執行,可以看到執行兩條打印。這裏begin和end就是event。
stap -v hello_world.stp
Pass 1: parsed user script and 476 library scripts using 116628virt/86416res/5608shr/81216data kb, in 260usr/20sys/280real ms.
Pass 2: analyzed script: 2 probes, 1 function, 0 embeds, 0 globals using 118212virt/88124res/5744shr/82800data kb, in 0usr/0sys/9real ms.
Pass 3: translated to C into "/tmp/stapcP149F/stap_95a8df27bac22dee8931f3f1827c6aeb_1046_src.c" using 118212virt/88124res/5744shr/82800data kb, in 0usr/0sys/0real ms.
Pass 4: compiled C into "stap_95a8df27bac22dee8931f3f1827c6aeb_1046.ko" in 2020usr/580sys/2963real ms.
Pass 5: starting run.
WARNING: module version mismatch (#1 SMP Tue May 12 20:00:21 CST 2020 vs #1 SMP Tue May 12 16:41:02 CST 2020), release 5.3.0-rc7
hello world
Bye
Pass 5: run completed in 0usr/30sys/539real ms.
(2) staprun
如果我們的輸入不是.stp腳本,而是一個用stap生成的模塊,那麼就用staprun來執行。
staprun - systemtap runtime
staprun [OPTIONS] MODULE [MODULE-OPTIONS]