SystemTap支持guru模式,通過-g選項來以這種模式執行SystemTap腳本。在guru模式下,嵌入的C代碼在“%{"和“%}"標記之間,這些代碼會原封不動地放到生成的模塊中。嵌入的C代碼不僅可以作為函數體,還可以出現在SystemTap描述中(例如函數等),示例如下:
%{
#include <linux/in.h>
#include <linux/ip.h>
%} /* <-- top level */
function read_iphdr:long(skb:long) %{ /* pure */
struct iphdr *iph = ip_hdr((struct sk_buff *)STAP_ARG_skb);
STAP_RETVALUE = (long)iph;
%} /* <-- function body */
/* Determines whether an IP packet is TCP, based on the iphdr: */
function is_tcp_packet:long(iphdr) {
protocol = @cast(iphdr, "iphdr")->protocol
return (protocol == %{ IPPROTO_TCP %}) /* <-- expression */
}
probe begin {
printf("SystemTap start!\n");
}
probe kernel.function("ip_local_deliver") {
iph = read_iphdr(pointer_arg(1));
printf("tcp packet ? %s\n", is_tcp_packet(iph) ? "yes" : "no");
}
在這裡read_iphdr函數就是使用嵌入的C代碼作為函數體,is_tcp_packet中是作為systemtap輔助函數中的一部分。
在使用嵌入C代碼作為函數體的函數中,訪問參數的值是以STAP_ARG_+參數名的形式,這種方式是最新版本的SystemTap中的方式。1.7及更早的版本是通過THIS->+參數名的方式。CentOS6.4中的SystemTap版本是1.8,所以你如果在SystemTap腳本中仍然使用老的訪問方式會報錯。同樣,最新的設置返回值的方式是STAP_RETVALUE,1.7及更早的版本是THIS->__retvalue。
由於在guru模式下,SystemTap對嵌入的C代碼沒有做任何的處理,所以如果在C代碼中出現異常的訪問或者其他錯誤,就會導致內核crash。不過SystemTap提供了kread宏來安全地訪問指針,如下所示:
struct net_device *dev;
char *name;
dev = kread(&(skb->dev));
name = kread(&(dev->name));
還有一點要特別注意,所有的SystemTap函數和probe都是在關閉中斷下執行,所以在所有嵌入的C代碼中都不能睡眠!