linux报错提示内存leak,用kmemleak检测内核内存泄漏

所谓内存泄漏(memory leak),是指分配出去的内存在用完之后忘了释放,造成内存浪费,可用的内存越来越少。内存泄漏是程序设计的错误导致的,既可能发生在用户程序里,也可能发生在内核中。

诊断内存泄漏问题的目标是定位为什么内存用完之后会忘了释放,最终都是需要阅读源代码,理解内在的逻辑,找出其中的错误。作为最基本的分析线索,我们至少需要观察内存的分配与释放操作,还有一些更高级的工具可以帮助我们找出无人引用的内存块以及最初分配它的backtrace,这就更有针对性了。诊断用户态程序内存泄漏最流行的工具是Valgrind,对于内核,类似的工具是kmemleak。

kmemleak的原理

kmemleak通过追踪kmalloc(), vmalloc(), kmem_cache_alloc()等函数,把分配内存的指针和大小、时间、stack trace等信息记录在一个rbtree中,等到调用free释放内存时就把相应的记录从rbtree中删除,也就是说rbtree中的记录就是已经分配出去但尚未释放的内存,其中有些内存尚未释放是因为还在被使用,这属于正常情况,而不正常的情况即内存尚未释放但又不会再被使用,就是“泄漏”的内存,那么如何找出泄漏的内存呢?kmemleak缺省每10分钟对内存做一次扫描,在内存中寻找rbtree中记录的地址,如果某个rbtree记录的地址在内存中找不到,就认为这个地址是无人引用的,以后也不可能再被用到,是“泄漏”的内存,然后,把这些泄漏的内存地址以及rbtree中记录的时间、大小、strack trace等相关信息通过 /sys/kernel/debug/kmemleak 这个接口展现给我们。

注:

kmemleak的扫描算法存在误报的可能,比如内存中碰巧有一个数据与rbtree中的某个地址相同,但它只是数据而非指针,kmemleak是无法分辨的,会把它当作访问内存的指针;再比如rbtree中的某个地址在内存中找不到,但程序可能还在用它,只是因为程序并没有直接保存访问地址,而是通过某种方式临时计算访问地址,这种情况kmemleak也无法分辨,会认为是泄漏。但是请注意,kmemleak 这个工具的目的是为了给进一步分析提供线索,并不需要绝对精确,小概率的误报并不影响这个工具的实用性。

怎样启用kmemleak

要启用kmemleak,前提是内核编译时在“Kernel hacking”中开启了 CONFIG_DEBUG_KMEMLEAK 选项。怎样知道一个运行系统的内核是否支持kmemleak呢?可以查看 /boot/config-$(uname -r) 配置文件中 CONFIG_DEBUG_KMEMLEAK 是否等于”y”。以RHEL6为例,它的debug kernel是支持kmemleak的,我们看它的config文件:

$ grep CONFIG_DEBUG_KMEMLEAK /boot/config-2.6.32-642.4.2.el6.x86_64.debug

CONFIG_DEBUG_KMEMLEAK=y

CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=20000

CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y

1

2

3

4

$grepCONFIG_DEBUG_KMEMLEAK/boot/config-2.6.32-642.4.2.el6.x86_64.debug

CONFIG_DEBUG_KMEMLEAK=y

CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=20000

CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y

CONFIG_DEBUG_KMEMLEAK=y

表示内核支持kmemleak;

CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y

表示kmemleak默认是关闭的,需要显式启用,启用的方式是在kernel command line中添加以下选项:

kmemleak=on

怎样使用kmemleak

kmemleak的用户接口是:

/sys/kernel/debug/kmemleak

发送指令和输出信息都是通过以上文件进行的。要访问这个文件,必须先挂载以下文件系统:

# mount -t debugfs nodev /sys/kernel/debug/

kmemleak缺省每10分钟扫描内存一次,找到可疑的内存泄漏会在syslog中写一条记录并提示通过/sys/kernel/debug/kmemleak可以看到更详细的信息:

# tail /var/log/messages

Aug 30 14:10:32 bj71s060-vm1 kernel: kmemleak: 1 new suspected memory leaks (see /sys/kernel/debug/kmemleak)

# cat /sys/kernel/debug/kmemleak

unreferenced object 0xffff88003cff1260 (size 32):

comm "softirq", pid 0, jiffies 4297625839

hex dump (first 32 bytes):

f0 a1 9b 35 00 00 00 00 0c 00 00 00 01 00 01 00 ...5............

da c0 70 3a 00 00 00 00 2a 00 00 00 00 00 00 00 ..p:....*.......

backtrace:

[] kmemleak_alloc+0x5e/0xe0

[] __kmalloc+0x1f2/0x330

[] virtqueue_add_buf+0x2c0/0x5e0 [virtio_ring]

[] start_xmit+0x1a7/0x460 [virtio_net]

[] dev_hard_start_xmit+0x22c/0x4a0

[] sch_direct_xmit+0x166/0x1d0

[] dev_queue_xmit+0x268/0x380

[] arp_xmit+0x58/0x60

[] arp_send+0x43/0x50

[] arp_solicit+0x236/0x2b0

[] neigh_timer_handler+0xf1/0x370

[] run_timer_softirq+0x20e/0x3e0

[] __do_softirq+0xff/0x260

[] call_softirq+0x1c/0x30

[] do_softirq+0xad/0xe0

[] irq_exit+0x95/0xa0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

# tail /var/log/messages

Aug3014:10:32bj71s060-vm1kernel:kmemleak:1newsuspectedmemoryleaks(see/sys/kernel/debug/kmemleak)

# cat /sys/kernel/debug/kmemleak

unreferencedobject0xffff88003cff1260(size32):

comm"softirq",pid0,jiffies4297625839

hexdump(first32bytes):

f0a19b35000000000c00000001000100...5............

dac0703a000000002a00000000000000..p:....*.......

backtrace:

[]kmemleak_alloc+0x5e/0xe0

[]__kmalloc+0x1f2/0x330

[]virtqueue_add_buf+0x2c0/0x5e0[virtio_ring]

[]start_xmit+0x1a7/0x460[virtio_net]

[]dev_hard_start_xmit+0x22c/0x4a0

[]sch_direct_xmit+0x166/0x1d0

[]dev_queue_xmit+0x268/0x380

[]arp_xmit+0x58/0x60

[]arp_send+0x43/0x50

[]arp_solicit+0x236/0x2b0

[]neigh_timer_handler+0xf1/0x370

[]run_timer_softirq+0x20e/0x3e0

[]__do_softirq+0xff/0x260

[]call_softirq+0x1c/0x30

[]do_softirq+0xad/0xe0

[]irq_exit+0x95/0xa0

也可以手工发起kmemleak的内存扫描:

# echo scan > /sys/kernel/debug/kmemleak

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值