歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux資訊 >> 更多Linux

使用 SystemTap 調試內核

    SystemTap 是一種新穎的 Linux 內核診斷工具,提供了一種從運行中的 Linux 內核快速和安全地獲取信息的能力。SystemTap 是內核開發人員和系統管理員的福音,因為這使得他們可以通過編寫或者重用簡單的腳本來收集內核的實時數據,而不需要再忍受修改源碼、編譯內核、重啟系統的漫長煎熬。本文介紹了 SystemTap 的安裝、使用和基本原理,並用一些有趣的例子揭示了 SystemTap 提供的強大能力。

    在 SystemTap 出現之前,對於 Linux 程序員或者系統管理員而言,調試內核往往是一場噩夢。例如,你懷疑傳遞給系統調用 read 的參數 fd 出了問題,想把它打印出來,你需要做的是:首先得到一份內核源碼,找到 sys_read() 的函數體中插入 printk() 語句,接下來重新編譯內核,然後用新的內核重新啟動系統。謝天謝地,你總算看到了你想要看到的東西,不過你馬上會發現遇到了一個新的麻煩:除非重新啟動系統到原來的內核,printk() 會無休止地打印下去。

    SystemTap 的目的就是要把人們從這種泥潭中解救出來。SystemTap 提供了一個簡單的命令行接口和強大的腳本語言,同時預定義了豐富的腳本庫。基於內核中的 kprobe,SystemTap允許你自由地從運行中的內核無害地收集調試信息和性能數據,來用於之後的分析和處理。你可以隨時開始或者停止這種收集過程,而無需漫長的修改代碼、編譯內核和重啟系統的悲慘循環。SystemTap 使得上面的問題變得簡單了,簡單得只需要一條命令就可以做到:

stap -e 'probe syscall.read { printf("fd = %d\n",fd) }

    SystemTap的功能和Sun的DTrace和IBM的dprobe工具相似。但是和它們不同的是, SystemTap是遵循GPL的開源軟件項目。它的出現使得Linux社區也擁有了功能強大而且易於使用的動態內核調試工具。目前,SystemTap 的主要開發成員來自於RedHat、IBM、Intel和Hitachi,其中還包括來自IBM中國開發中心的工程師。

安裝SystemTap

在安裝SystemTap之前,需要確保系統中已經安裝了其它兩個軟件包:

kernel-debuginfo RPM:SystemTap需要通過內核調試信息來定位內核函數和變量的位置。對於通常的發行版,並沒有安裝kernel-debuginfo RPM,我們可以到發行版的下載站點下載。對於我的ThinkPad上的Fedora Core 6,這個地址是: http://download.fedora.redhat.com/pub/fedora/linux/core/6/i386/debug/ elfutils RPM:SystemTap需要elfutils軟件包提供的庫函數來分析調試信息。目前的SystemTap要求安裝elfutils-0.123以上版本。目前最新的版本是0.124-0.1。如果需要,我們可以從SystemTap的站點下載RPM或者源碼來升級。下載地址是: FTP://sources.redhat.com/pub/SystemTap/elfutils/i386/

接下來就可以安裝SystemTap了,這有通過RPM或者源碼安裝兩種方式:

1. 通過RPM安裝 Fedora Core 6缺省情況下已經安裝了systemtap。如果沒有,也可以從如下的地址下載: http://download.fedora.redhat.com/pub/fedora/linux/core/updates/testing/6/i386/SystemTap-0.5.10-1.fc6.i386.rpm

2.通過源碼安裝:

從SystemTap的FTP站點下載最新的源碼

ftp://sources.redhat.com/pub/SystemTap/snapshots/SystemTap-20061104.tar.bz2

然後安裝如下:

/root > tar -jxf SystemTap-20061104.tar.bz2 /root > cd src /root/src> ./configure /root/src> make /root/src> make install

運行SystemTap

運行SystemTap首先需要root權限。

運行SystemTap有三種形式:

1. 從文件(通常以.stp作為文件名後綴)中讀入並運行腳本:stap [選項] 文件名

2. 從標准輸入中讀入並運行腳本: stap [選項] -

3. 運行命令行中的腳本:stap [選項] -e 腳本

4. 直接運行腳本文件(需要可執行屬性並且第一行加上#!/usr/bin/stap):./腳本文件名使用"Ctrl+C"中止SystemTap的運行。

systemtap的選項還在不斷的擴展和更新中,其中最常用的選項包括:

-v -- 打印中間信息

-p NUM -- 運行完Pass Num後停止(缺省是運行到Pass 5)

-k -- 運行結束後保留臨時文件不刪除

-b -- 使用RelayFS文件系統來將數據從內核空間傳輸到用戶空間

-M -- 僅當使用-b選項時有效,運行結束時不合並每個CPU的單獨數據文件

-o FILE -- 輸出到文件,而不是輸出到標准輸出

-c CMD -- 啟動探測後,運行CMD命令,直到命令結束後退出

-g -- 采用guru模式,允許腳本中嵌入C語句

其它更多選項請參看stap的手冊。

SystemTap的語法

我們利用一個簡單的systemtap腳本來介紹一下SystemTap的語法:

#!/usr/local/bin/stap global count function report(stat) { printf("stat=%d\n", stat) } probe kernel.function("sys_read") { ++count } probe end { report() }

探測點(probe):每個systemtap腳本中至少需要定義一個探測點,也就是指定了在內核的什麼位置進行探測。探測點名稱後面緊跟的一組大括號內定義了每次內核運行到該探測點時需要運行的操作,這些操作完成後再返回探測點,繼續下面的指令。這裡給出了systemtap目前支持的所有探測點類型。 全局變量(global):用來定義全局變量。單個探測點函數體中使用的局部變量不需要預先定義,但是如果一個變量需要在多個探測點函數體中使用,則需要定義為全局變量。 函數(function):用來定義探測點函數體中需要用到的函數。除了可以用腳本語言定義函數以外,還可以用C語言來定義函數,只是這時函數名後面的大括號對需要換成%{ %}。例如,前面的report()函數可以寫成:

function report(stat) %{ _stp_printf("stat=%d\n", THIS->stat); %}

SystemTap的例子

了解了SystemTap的基本用法,下面讓我們來看幾個有趣的例子。

統計當前系統中調用最多的前10個系統調用

    在進行性能分析的時候,我們常常需要知道那些函數調用次數最多,才能有的放矢地展開分析。下面這個簡單的例子可以打印出在過去的5秒鐘裡調用次數最多的那些系統調用。

#!/usr/bin/env stap # # display the top 10 syscalls called in last 5 seconds # global syscalls function print_top () { cnt=0 log ("SYSCALL\t\t\t\tCOUNT") foreach ([name] in syscalls-) { printf("%-20s\t\t%5d\n",name, syscalls[name]) if (cnt++ == 10) break } printf("--------------------------------------\n") delete syscalls } probe syscall.* { syscalls[probefunc()]++ } probe timer.ms(5000) { print_top () }

它的輸出結果一目了然:

看看是誰在偷偷動我的文件

    有時候,我們如果中了惡意的病毒軟件,會發現某些文件莫名其妙的被修改,下面這個例子可以幫你監視誰在修改你的文件。

#!/usr/bin/env stap # # monitor who is messing my file of secrets # probe generic.fop.open { if(filename == "secrets") printf("%s is opening my file: %s\n", execname(), filename) }

我們運行這個腳本,在另外一個窗口做一些操作,來看看它的輸出結果:

 

更多的請看:http://www.QQread.com/windows/2003/index.Html

打印ANSI字符串

    SystemTap不僅僅是一個簡單的調試工具,強大的腳本語言能力讓它同樣能做一些有趣的事情,下面這個例子就可以對輸出的字符進行美化:

#!/usr/bin/env stap # # print colorful ANSI strings # probe begin { printf("a \\ b "); for (c = 40; c < 48; c++) printf(" %d ", c); printf("\12"); for (l = 0; l < 71; l++) printf("-"); printf("\12"); for (r = 30; r < 38; r++) for (t = 0; t < 2; t++) { printf("%d ", r); for (c = 40; c < 48; c++) printf("\033[%d;%d%s %s \033[0;0m", r, c, !t ? "m" : ";1m", !t ? "Normal" : "Bold "); printf("\12"); } exit(); }

來看看它的輸出:

 

SystemTap的基本原理

   現在,大家已經熟悉了SystemTap的基本用法。在結束之前,讓我們再來了解一下SystemTap的基本原理和工作流程以加深理解。

    可以看出,SystemTap運行的過程依次分為五個階段,通常稱為Pass 1 - Pass 5。就像前面介紹用法的時候提到的,在命令行中加上-p NUM選項可以使得SystemTap在運行完Pass NUM之後停止,而不是運行到Pass 5。這允許你分析SystemTap在每一個階段的輸出,對於調試腳本尤其有用。

下面來介紹每一個階段的主要功能:

Pass 1 - parse:這個階段主要是檢查輸入腳本是否存在語法錯誤,例如大括號是否匹配,變量定義是否規范等 Pass 2 - elaborate:這個階段主要是對輸入腳本中定義的探測點或者用到的函數展開,不但需要綜合SystemTap的預定義腳本庫,還需要分析內核或者內核模塊的調試信息 Pass 3 - translate: 在這個階段,將展開後的腳本轉換成C文件。前三個階段的功能類似於編譯器,將.stp文件編譯成為完整的.c文件,因此又被合起來稱為轉換器(translator) Pass 4 - build:在這個階段,將C源文件編譯成內核模塊,在這過程中還會用到SystemTap的運行時庫函數。 Pass 5 - run:這個階段,將編譯好的內核模塊插入內核,開始進行數據收集和傳輸。

小結

    SystemTap是一個全新的工具,但已經表現出了強大的功能和廣泛的適用性。SystemTap使得動態收集Linux內核信息和性能數據變得輕而易舉,這就使人可以從繁瑣的數據采集中解放出來,而專注於數據的處理和分析,這無疑是內核開發人員和系統管理人員的福音。隨著越來越多用戶的體驗,越來越多的bug會被報告和修正,越來越多的新功能會被添加,SystemTap也會變得越來越穩定和完善。

原文鏈接:http://www-128.ibm.com/developerworks/cn/linux/l-systemtap/index.html




Copyright © Linux教程網 All Rights Reserved