首页 > 代码库 > 红帽Linux故障定位技术详解与实例(4)

红帽Linux故障定位技术详解与实例(4)

红帽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之间共享参数的方法. 代码如下:

 

  1. arp_probe.c /*  
  2. * arp_probe.c, by Qianfeng Zhang (frzhang@redhat.com)  
  3. */  
  4.  
  5. #include   
  6. #include   
  7. #include   
  8. #include   
  9. #include   
  10. #include   
  11. #include   
  12. #include   
  13.  
  14. MODULE_AUTHOR("frzhang@redhat.com");  
  15. MODULE_DESCRIPTION("A module to track the call results of ip_route_input() inside arp_process using jprobe and kretprobe");  
  16. MODULE_LICENSE("GPL");  
  17.  
  18. static int j_arp_process(struct sk_buff *skb)  
  19. {  
  20. struct net_device *dev = skb->dev;  
  21. struct in_device *in_dev;  
  22. int no_addr, rpf;  
  23.  
  24. in_dev = in_dev_get(dev);  
  25. no_addr = ( in_dev->ifa_list == NULL );  
  26. rpf = IN_DEV_RPFILTER(in_dev);  
  27. in_dev_put(in_dev);  
  28. printk("\narp_process() is called with interface device %s, in_dev(no_addr=%d,rpf=%d) \n", dev->name, no_addr, rpf);  
  29. jprobe_return();  
  30. return(0);  
  31. };  
  32.  
  33. static int j_fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,  
  34. struct net_device *dev, __be32 *spec_dst, u32 *itag, u32 mark)  
  35.  
  36. {  
  37. printk("fib_validate_source() is called with dst=0x%x, oif=%d \n", dst, oif);  
  38. jprobe_return();  
  39. return(0);  
  40. };  
  41.  
  42. static struct jprobe my_jp1 = {  
  43. .entry = j_arp_process,  
  44. .kp.symbol_name = "arp_process" 
  45. };  
  46.  
  47. static struct jprobe my_jp2 = {  
  48. .entry = j_fib_validate_source,  
  49. .kp.symbol_name = "fib_validate_source" 
  50. };  
  51.  
  52. static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)  
  53. {  
  54. printk("Calling: %s()\n", ri->rp->kp.symbol_name);  
  55. return(0);  
  56. };  
  57.  
  58. static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)  
  59. {  
  60. int eax;  
  61.  
  62. eax = regs->ax & 0xffff ;  
  63. printk("Returning: %s() with a return value: 0x%lx(64bit) 0x%x(32bit)\n", ri->rp->kp.symbol_name, regs->ax, eax);  
  64.  
  65. return(0);  
  66. };  
  67.  
  68. static int fib_lookup_entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)  
  69. {  
  70. struct fib_result *resp;  
  71.  
  72. resp = (struct fib_result *) regs->dx;  
  73. printk("Calling: %s()\n", ri->rp->kp.symbol_name);  
  74. *((struct fib_result **)ri->data) = resp;  
  75.  
  76. return(0);  
  77. };  
  78.  
  79. static int fib_lookup_return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)  
  80. {  
  81. struct fib_result *resp;  
  82. int eax;  
  83.  
  84. eax = regs->ax & 0xffff ;  
  85. resp = *((struct fib_result **) ri->data);  
  86. printk("Returning: fib_lookup() with a return value: 0x%lx(64bit) 0x%x(32bit), result->type: %d\n", regs->ax, eax, resp->type);  
  87.  
  88. return(0);  
  89. }  
  90.  
  91. static struct kretprobe my_rp1 = {  
  92. .handler = return_handler,  
  93. .entry_handler = entry_handler,  
  94. .kp.symbol_name = "ip_route_input_slow" 
  95. };  
  96.  
  97. static struct kretprobe my_rp2 = {  
  98. .handler = return_handler,  
  99. .entry_handler = entry_handler,  
  100. .kp.symbol_name = "fib_validate_source" 
  101. };  
  102.  
  103. static struct kretprobe my_rp3 = {  
  104. .handler = fib_lookup_return_handler,  
  105. .entry_handler = fib_lookup_entry_handler,  
  106. .kp.symbol_name = "fib_lookup",  
  107. .data_size = sizeof(struct fib_result *)  
  108. };  
  109.  
  110. static int __init init_myprobe(void)  
  111. {  
  112. int ret;  
  113.  
  114. printk("RTN_UNICAST is %d\n", RTN_UNICAST);  
  115. if ( (ret = register_jprobe(&my_jp1)) 0) {  
  116. printk("register_jprobe %s failed, returned %d\n", my_jp1.kp.symbol_name, ret);  
  117. return(-1);  
  118. }  
  119.  
  120. if ( (ret = register_jprobe(&my_jp2)) 0) {  
  121. printk("register_jprobe %s failed, returned %d\n", my_jp2.kp.symbol_name, ret);  
  122. return(-1);  
  123. }  
  124.  
  125. if ( (ret = register_kretprobe(&my_rp1)) 0 ) {  
  126. printk("register_kretprobe %s failed, returned %d\n", my_rp1.kp.symbol_name, ret);  
  127. unregister_jprobe(&my_jp1);  
  128. unregister_jprobe(&my_jp2);  
  129. return(-1);  
  130. }  
  131.  
  132. if ( (ret = register_kretprobe(&my_rp2)) 0 ) {  
  133. printk("register_kretprobe %s failed, returned %d\n", my_rp2.kp.symbol_name, ret);  
  134. unregister_jprobe(&my_jp1);  
  135. unregister_jprobe(&my_jp2);  
  136. unregister_kretprobe(&my_rp1);  
  137. return(-1);  
  138. }  
  139.  
  140. if ( (ret = register_kretprobe(&my_rp3)) 0 ) {  
  141. printk("register_kretprobe %s failed, returned %d\n", my_rp3.kp.symbol_name, ret);  
  142. unregister_jprobe(&my_jp1);  
  143. unregister_jprobe(&my_jp2);  
  144. unregister_kretprobe(&my_rp1);  
  145. unregister_kretprobe(&my_rp2);  
  146. return(-1);  
  147. }  
  148.  
  149. return 0;  
  150. }  
  151.  
  152.  
  153. static void __exit rel_myprobe(void)  
  154. {  
  155. unregister_jprobe(&my_jp1);  
  156. unregister_jprobe(&my_jp2);  
  157. unregister_kretprobe(&my_rp1);  
  158. unregister_kretprobe(&my_rp2);  
  159. unregister_kretprobe(&my_rp3);  
  160. }  
  161.  
  162. module_init(init_myprobe);  
  163. module_exit(rel_myprobe);  
  164.  
  165. Makefile obj-m += arp_probe.o  
  166. Making #> make -C /usr/src/kernels/2.6.32-71.el6.x86_64/ M=`pwd` modules 

Linux故障定位技术详解与实例的内容介绍完了,希望通过本文红帽Linux故障定位技术的学习能对你有所帮助!

红帽Linux故障定位技术详解与实例(4)