標籤:des http os io 使用 ar strong 2014 div
紅帽Linux故障定位技術詳解與執行個體(4)
線上故障定位就是在故障發生時, 故障所處的作業系統環境仍然可以訪問,故障處理人員可通過console, ssh等方式登入到作業系統上,在shell上執行各種操作命令或測試程式的方式對故障環境進行觀察,分析,測試,以定位出故障發生的原因。
AD:2014WOT全球軟體技術峰會北京站 課程視頻發布
6、使用kprobe來觀察核心功能的執行執行個體
kprobe是SystemTap對核心功能進行probing的功能在核心中的實現,由於核心中提供了正式的API來使用kprobe,所以對很多核心程式員來說,也許直接使用kprobe比使用SystemTap更方便. 核心中提供了三種類型的kprobe處理函數,分別是jprobe, kprobe, kretprobe, 下面的代碼用這三個probe觀察在TCP/IP的arp_process函數執行中對ip_route_input()調用的返回結果.這個代碼還展示了在同一個函數probe的Entry handler和Ret handler之間共用參數的方法. 代碼如下:
- arp_probe.c /*
- * arp_probe.c, by Qianfeng Zhang ([email protected])
- */
-
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- MODULE_AUTHOR("[email protected]");
- MODULE_DESCRIPTION("A module to track the call results of ip_route_input() inside arp_process using jprobe and kretprobe");
- MODULE_LICENSE("GPL");
-
- static int j_arp_process(struct sk_buff *skb)
- {
- struct net_device *dev = skb->dev;
- struct in_device *in_dev;
- int no_addr, rpf;
-
- in_dev = in_dev_get(dev);
- no_addr = ( in_dev->ifa_list == NULL );
- rpf = IN_DEV_RPFILTER(in_dev);
- in_dev_put(in_dev);
- printk("\narp_process() is called with interface device %s, in_dev(no_addr=%d,rpf=%d) \n", dev->name, no_addr, rpf);
- jprobe_return();
- return(0);
- };
-
- static int j_fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
- struct net_device *dev, __be32 *spec_dst, u32 *itag, u32 mark)
-
- {
- printk("fib_validate_source() is called with dst=0x%x, oif=%d \n", dst, oif);
- jprobe_return();
- return(0);
- };
-
- static struct jprobe my_jp1 = {
- .entry = j_arp_process,
- .kp.symbol_name = "arp_process"
- };
-
- static struct jprobe my_jp2 = {
- .entry = j_fib_validate_source,
- .kp.symbol_name = "fib_validate_source"
- };
-
- static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
- {
- printk("Calling: %s()\n", ri->rp->kp.symbol_name);
- return(0);
- };
-
- static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
- {
- int eax;
-
- eax = regs->ax & 0xffff ;
- printk("Returning: %s() with a return value: 0x%lx(64bit) 0x%x(32bit)\n", ri->rp->kp.symbol_name, regs->ax, eax);
-
- return(0);
- };
-
- static int fib_lookup_entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
- {
- struct fib_result *resp;
-
- resp = (struct fib_result *) regs->dx;
- printk("Calling: %s()\n", ri->rp->kp.symbol_name);
- *((struct fib_result **)ri->data) = resp;
-
- return(0);
- };
-
- static int fib_lookup_return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
- {
- struct fib_result *resp;
- int eax;
-
- eax = regs->ax & 0xffff ;
- resp = *((struct fib_result **) ri->data);
- printk("Returning: fib_lookup() with a return value: 0x%lx(64bit) 0x%x(32bit), result->type: %d\n", regs->ax, eax, resp->type);
-
- return(0);
- }
-
- static struct kretprobe my_rp1 = {
- .handler = return_handler,
- .entry_handler = entry_handler,
- .kp.symbol_name = "ip_route_input_slow"
- };
-
- static struct kretprobe my_rp2 = {
- .handler = return_handler,
- .entry_handler = entry_handler,
- .kp.symbol_name = "fib_validate_source"
- };
-
- static struct kretprobe my_rp3 = {
- .handler = fib_lookup_return_handler,
- .entry_handler = fib_lookup_entry_handler,
- .kp.symbol_name = "fib_lookup",
- .data_size = sizeof(struct fib_result *)
- };
-
- static int __init init_myprobe(void)
- {
- int ret;
-
- printk("RTN_UNICAST is %d\n", RTN_UNICAST);
- if ( (ret = register_jprobe(&my_jp1)) < 0) {
- printk("register_jprobe %s failed, returned %d\n", my_jp1.kp.symbol_name, ret);
- return(-1);
- }
-
- if ( (ret = register_jprobe(&my_jp2)) < 0) {
- printk("register_jprobe %s failed, returned %d\n", my_jp2.kp.symbol_name, ret);
- return(-1);
- }
-
- if ( (ret = register_kretprobe(&my_rp1)) < 0 ) {
- printk("register_kretprobe %s failed, returned %d\n", my_rp1.kp.symbol_name, ret);
- unregister_jprobe(&my_jp1);
- unregister_jprobe(&my_jp2);
- return(-1);
- }
-
- if ( (ret = register_kretprobe(&my_rp2)) < 0 ) {
- printk("register_kretprobe %s failed, returned %d\n", my_rp2.kp.symbol_name, ret);
- unregister_jprobe(&my_jp1);
- unregister_jprobe(&my_jp2);
- unregister_kretprobe(&my_rp1);
- return(-1);
- }
-
- if ( (ret = register_kretprobe(&my_rp3)) < 0 ) {
- printk("register_kretprobe %s failed, returned %d\n", my_rp3.kp.symbol_name, ret);
- unregister_jprobe(&my_jp1);
- unregister_jprobe(&my_jp2);
- unregister_kretprobe(&my_rp1);
- unregister_kretprobe(&my_rp2);
- return(-1);
- }
-
- return 0;
- }
-
-
- static void __exit rel_myprobe(void)
- {
- unregister_jprobe(&my_jp1);
- unregister_jprobe(&my_jp2);
- unregister_kretprobe(&my_rp1);
- unregister_kretprobe(&my_rp2);
- unregister_kretprobe(&my_rp3);
- }
-
- module_init(init_myprobe);
- module_exit(rel_myprobe);
-
- Makefile obj-m += arp_probe.o
- Making #> make -C /usr/src/kernels/2.6.32-71.el6.x86_64/ M=`pwd` modules
Linux故障定位技術詳解與執行個體的內容介紹完了,希望通過本文紅帽Linux故障定位技術的學習能對你有所協助!
原文地址:http://beareyes.com.cn/2/lib/201109/27/20110927182_0.htm
紅帽Linux故障定位技術詳解與執行個體(4)