Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1504265
  • 博文数量: 228
  • 博客积分: 1698
  • 博客等级: 上尉
  • 技术积分: 3241
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-24 21:49
个人简介

Linux

文章分类

全部博文(228)

文章存档

2017年(1)

2016年(43)

2015年(102)

2014年(44)

2013年(5)

2012年(30)

2011年(3)

分类: LINUX

2015-07-30 21:31:20

前段时间上线了一个新的Kernel优化项目,用于优化协议栈的性能。运维监控的生产环境中出现了SKB的内存泄漏,得知该问题时,问题已经出现了两次。
重现一次大约需要一个月左右的时间,泄漏的比较慢,由于我们上线Kernel的协议栈优化,因此问题分了过来。

早期出现的两次是运维开发的同事在对应,沟通了一下,只能确定是SKB泄漏,无法确定是那个模块,那个业务流程泄漏。由于重现问题较慢,生产环境直接验证的风险比较大,想了半天没有好的办法,隔离业务排查的周期太长,我决定dump内存。

基本的思路是写了个内核模块,创建一个线程,然后去遍历slab的内存表了,如下:

由于skbuff_head_cache的定义为static struct kmem_cache *skbuff_head_cache __read_mostly,不修改内核的情况下无法在我们模块中使用,采用解析内核符号表的方式来获取该kmem_cache的地址。<slab的组织原理,见以前的源码分析>

1.  获取skbuff_head_cache的地址并传递给内核模块,cat /proc/kallsyms | grep -w skbuff_head_cache | cut -d " " -f 1
2.  创建一个内核线程,做如下工作,简单介绍如下:
点击(此处)折叠或打开
  1. for_each_online_node(node) {
  2.                 slab_list3 = cachep->nodelists[node];
  3.                 if (unlikely(slab_list3 == NULL))
  4.                         continue;
  5.                 spin_lock_irqsave(&slab_list3->list_lock, flags);
  6.                 list_for_each_entry(slab, &slab_list3->slabs_full, list) {
  7.                         if (unlikely(index > RECORD_MAX_NUM - 1))
  8.                                 break;
  9.                         slab_ac[index++] = (ulong)slab;
  10.                 }
  11.                 spin_unlock_irqrestore(&slab_list3->list_lock, flags);
  12.         }
遍历online node,将slabs_full上的slab节点地址全部记录在临时申请的数组slab_ac中,这里的锁是关中断的自旋锁,不能持久占用,所以先保存一下,延迟遍历。

3. 遍历已经保存的slab节点,注意检查一下slab的inuse和cache->num是否相等,我们只检查被占满的slab,因为泄漏的概率比较大。
另外,由于已经停止流量很长时间,所以当前也不会有大量的skb的申请与释放了。
4. 选中slab后,根据cache->num进行遍历,采用基地址加偏移的方式,如下:

点击(此处)折叠或打开

  1. for (i = 0; i < num; i++) {
  2.                 struct sk_buff *skb = (struct sk_buff *)(slabp->s_mem + i * objsize);
  3.                 print_skb_stats(skb);
  4. }
然后,强制解析skb,即不对skb做任何假设,对报文体从头开始解析。将解析到的结果输出到文件中,并输出skb控制结构中的其他辅助信息。

由于泄漏的规模巨大,接近600万,因此根据文件中的skb信息,很轻松的找到一些相似的信息。比如IP地址信息,比如skb上的一些标签,依据这些信息很容易的找到出现问题的业务模块,和相关流程。并将问题转移给相关模块,顺利解决。

只是一个解决问题的工具,记录一下相关思路,不上传代码了。

阅读(2202) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~