即使對於老練的程序員和系統管理員,應用程序開發和故障排除也是艱難的任務。即使有了最好的調試器,程序員有時候仍然希望用簡單的打印語句檢查應用程序正在執行的操作。IBM® AIX® V6 增加了一種新的調試工具,ProbeVue。本文簡要介紹 ProbeVue的用法以及相關聯的編程和腳本語言,並通過一個簡單的示例程序演示 ProbeVue的用途和潛在價值。
簡介
ProbeVue這種跟蹤工具使用戶可以動態地跟蹤正在運行的程序。ProbeVue的主要接口是 VUE 語言。VUE 既是編程語言,也是腳本語言。VUE 語言與 C 語言和AIX 可用的腳本語言相似。
VUE 語法
ProbeVue腳本的基本形式與結構良好的C程序和awk 腳本相似。Vue腳本文件的一般形式如下:
Variable definitions
Begin {
}
Probe clauses
End {
}
變量部分
在變量部分中定義全局變量。與 C 語言一樣,可以在文件中的其它地方指定臨時變量。VUE 支持以下變量類型:
C-89數據類型(包括有符號和無符號)short、int、long、long long、float 和double。對於浮點變量的操作只限於簡單的賦值表達式和作為 VUE 函數的變量。
String數據類型代表字符串字面值。例如,String fooString[20] 聲明一個長度為 20的字符串字面值。只需用fooString = “My String” 初始化 fooString。可以使用+ 操作符連接多個字符串字面值。
List數據類型表示一組整數類型的值。例如,fooList = list() 創建 List fooList。使用append 函數在 fooList 中添加值:append( fooList, value ),其中的value 可以是另一個列表或整數變量。除了append 函數之外,List數據類型還支持 avg() 函數(計算列表的平均值)、min() 函數(判斷列表中的最小值)、max() 函數(判斷列表中的最大值)和count() 函數(返回列表的大小,即列表中的條目數量)。
probev_timestamp_t是一種特殊的數據類型,用來從 VUE 時間戳函數返回值。返回的值采用AIX 內部格式。
環境變量
在環境變量名稱前面加上 $(美元)符號,就可以在 Vue腳本中使用環境變量。在默認情況下,環境變量存儲整數值。要想保證傳遞字符串,環境變量必須用雙引號定義變量:export MYENV=\”123\” 傳遞字符串 123,而 export MYENV=123 傳遞整數值一百二十三。
除了傳遞環境變量之外,VUE 還支持幾個內置的環境變量:
__CPID是 ProbeVue命令創建的子進程的進程 ID。
__CPTID是線程 ID。
Begin 部分
begin 部分是 Vue腳本中用來執行變量初始化的部分。在腳本開始執行時調用這個部分,而且只執行一次。
探測子句(Probe clauses)
探測子句部分包含程序邏輯。程序員在這個部分中定義各個探測點。下一節詳細討論各種探測類型,這些探測類型包括系統調用、用戶函數和內部。
探測類型
ProbeVue提供以下探測類型:
系統調用探測
用戶函數探測
內部探測
系統調用探測
系統調用探測(即 syscall 探測)用來探測 libc 庫和內核中的函數。可以為函數調用的進入或退出定義探測。系統調用探測的一般形式如下:@@syscall:<process_ID>:<system_call_name>:<entry|exit>
其中:
<process_ID>是要探測的進程(例如,123675 或表示所有進程的*)
<system_call_name>是要探測的系統調用(例如,read)
<entry> 對函數調用的進入執行探測
<exit> 對函數調用的退出執行探測
通過使用系統調用探測,可以在 Vue腳本中使用輸入參數和返回值。為了訪問輸入參數,Vue腳本必須聲明要探測的函數的函數原型。例如:int read( int fd, char *buf, unsigned long size );
指定這一行,Vue腳本就能夠訪問 fd、buf 和size 參數。使用一個特殊的內置變量 __arg3 捕捉函數的返回值。
用戶函數探測
用戶函數探測應用於應用程序代碼級探測。用戶函數探測的一般形式如下:@@uft:<processID>:*:<function_name>:entry
其中:
process_ID是要探測的可執行程序的進程 ID
function_name是要探測其進入的用戶函數
與系統調用探測不同,用戶函數探測必須指定一個進程 ID,而且只能探測函數的進入。
內部探測
內部探測是以一定的時間間隔執行的探測。內部探測的一般形式如下:@@interval:*:clock:<# milliseconds>
其中 <# milliseconds> 以 100ms 為單位定義時間間隔。
命令語法
ProbeVue命令行提供各種選項。本文主要關注 ProbeVue命令的以下形式。後面的ProbeVue示例腳本也使用這種形式。ProbeVue[ -X Program_name [ -A "Arguments_to_program" ] ]
[ Script_name [ Arguments_to_script ] ]
其中: -X 啟動一個程序並在啟動程序之前啟用探測。 -A 為使用-X 標志指定的程序指定參數。 Script_name 包含要運行的ProbeVue腳本的文件。
指定 –X 選項,這會在指定的命令執行期間運行 ProbeVue。ProbeVue的這種用法有助於探測單一程序。
系統調用探測示例
前面已經簡要解釋了腳本語法和探測類型,現在來看一個使用系統調用探測的簡單ProbeVue腳本。
清單1:系統調用ProbeVue腳本示例
/* Function prototype for read in order to access input args */
int read( int fd, char *buf, unsigned long size );
String sFormat0[10];
String sFormat1[10];
String sLen[2];
@@BEGIN
{
/* Initialize printf format strings */
sLen = "9";
sFormat0 = "%" + sLen + "d,";
sFormat1 = "%" + sLen + "d," + "%" + sLen + "d\n";
sFormat2 = "%" + sLen + "s,%" + sLen + "s,%" + sLen + "s\n";
/* Print header */
printf( sFormat2, "Requested", "Actual", "Average" );
/* Create list to maintain rolling average */
rollingAvg = list();
}
/* Probe to print the size of the read buffer. */
@@syscall:*:read:entry
/* Only for the currently executing program. */
when ( $__CPID == __pid ) {
/* __arg3 represents the size of the read buffer. */
printf( sFormat0, __arg3 );
}
/* Probe to print the actual number of bytes read i.e. the return value from read. */
@@syscall:*:read:exit
/* Only for the currently executing program. */
when ( $__CPID == __pid ) {
/* Append return value (__rv) to list */
append( rollingAvg, __rv );
printf( sFormat1, __rv, avg( rollingAvg) );
}
@@END
{
}
顯示數據
這個系統調用ProbeVue腳本示例的輸出采用Microsoft® Excel® CSV(逗號分隔的值)格式。收集和格式化數據的方式數不勝數,但這個簡單的腳本和格式可以獲取應用程序的信息,在以前,這需要通過應用程序中的特定代碼來實現。通過使用ProbeVue,在應用程序之外執行這個腳本的代碼。下面是這個程序的輸出示例:ProbeVue-X /usr/bin/tar -A "-cf /dev/null /scratch/bcobb/ProbeVue" ./p2.e | tee t.csv
Requested Actual Average 4096 1703 1703 4096 0 851 4096 4096 1933 4096 1160 1739 4096 314 1454 4096 1865 1523 4096 575 1387 4096 575 1286 4096 371 1184
使用這個輸出創建一個如下圖所示的圖表。
清單1 系統調用ProbeVue腳本產生的圖表
結束語
本文從程序員的角度簡要介紹了AIX工具集中的ProbeVue。本文討論了ProbeVue的基本概念,包括ProbeVue腳本的一般形式、VUE編程語言和一個簡單但有意義的示例腳本。