参考上面的文章。下面是自己的笔记
内存泄漏
内存泄漏:忘记释放内存而导致内存被耗尽,从而导致系统崩溃。。
内存泄漏的根本原因:用户没有释放不再使用的动态申请的内存(在内核中由 memblock_alloc
、kmalloc
、vmalloc
、kmem_cache_alloc
等函数申请的内存),一般来说,没有被指针引用(指向)的内存都是不再使用的内存。因为这些内存已经丢失了其地址信息,从而导致内核不能再使用这些内存。
内核里面所有的指针: 内核数据段
、内核栈
和 动态申请的内存块中
。
但内核并没有对指针进行记录,也就是说内核并不知道这些区域是否存在指针。那么内核只能够把这些区域当成是由指针组成的,也就是说把这些区域中的每个元素都当成是一个指针。但是并不是每一个元素都是一个指针,因此,kmemleak只是为了找到内核中疑似内存泄露的地方。
动态记录内存块:
kmemleak 机制用于分析由 memblock_alloc
、kmalloc
、vmalloc
、kmem_cache_alloc
等函数申请的内存是否存在泄漏。
分析的依据是:扫描内核中所有的指针,然后判断这些指针是否指向了由 memblock_alloc
、kmalloc
、vmalloc
、kmem_cache_alloc
等函数申请的内存块。如果存在没有指针引用的内存块,那么就表示可能存在内存泄漏。
内核使用 kmemleak_object
对象来记录这些内存块的信息,然后通过一棵红黑树把这些 kmemleak_object
对象组织起来(使用内存块的地址作为键),如下图所示:
所以内存泄漏检测的原理是:
-
遍历内核中所有的指针,然后从红黑树中查找是否存在对应的内存块,如果存在就把内存块打上标记。
-
所有指针扫描完毕后,再遍历红黑树中所有
kmemleak_object
对象。如果发现没有打上标记的内存块,说明存在内存泄漏(也就是说,存在没有被指针引用的内存块),并且将对应的内存块信息记录下来。
kmemleak 实现
内存泄漏检测
当开启内存泄漏检测时,内核将会创建一个名为 kmemleak
的内核线程来进行检测。
在分析内存检测的实现之前,我们先来了解一下关于 kmemleak_object
对象的三个概念:
-
白色节点:表示此对象没有被指针引用(
count
字段少于min_count
字段)。 -
灰色节点:表示此对象被一个或多个指针引用(
count
字段大于或等于min_count
字段)。 -
黑色节点:表示此对象不需要被扫描(
min_count
字段等于 -1)
扫描完毕后,所有白色的节点就是可能存在内存泄漏的内存块。