深入理解内存泄漏检查kmemleak

原创 Linux阅码场 2022-02-25 08:00

作者简介

bang,linux内核爱好者,目前就职于杭州某安防公司,主要从事于SOC的bring up及驱动开发,喜欢分析linux内核内存管理和调度子系统。



1.概述


内存泄漏是我们工作中经常遇到的问题,比如随着业务的持续运行,系统中可用内存在快速减少,导致某个重要的业务进程被OOM kill掉了。内存泄漏往往都是很严重的问题,尤其是内核态的内存泄漏,危害更大。每次泄漏一块内存,该块内存就成为一个黑洞,如果是严重的内核态内存泄漏,系统将很快变的无法正常使用,通常需要重启设备或者服务器才能解决问题。我们肯定不希望这种事情发生,那就需要想办法把内存泄漏提前暴露在测试环境中。要解决内存泄漏问题,首先需要了解内存泄漏的特点。内存泄漏分为用户态的内存泄漏和内核态的内存泄漏,我们本文主要关注的是内核态的内存泄漏。工作中比较常见的内存泄漏按照发生泄漏的频率可以划分以下几种类型:


  • 1、一次性内存泄漏,只在初始化过程中或某一次条件触发产生的内存泄漏。

  • 2、偶发性内存泄漏,在某种条件下偶尔触发产生的内存泄漏。

  • 3、频发性内存泄漏,内存泄漏点被频繁的触发。


对于频发性内存泄漏我们有比较多的调试手段去定位,比如我们可以先通过/proc/meminfo信息大致确定下内存泄漏发生在哪个模块中,再通过其他手段进一步定位。如果观察到vmalloc异常,可以通过/proc/vmallocinfo信息分析定位。如果观察到slab内存异常,可以通过slabinfo/sys/kernel/slab/*/alloc_callsfree_calls去辅助定位问题。而对于一次性的或者偶发性的内存泄漏确很难去通过/proc/meminfo信息快速分析定位,且大量的一次性或偶发性内存泄漏,同样给系统造成额外的内存压力。而本文介绍的kmemleak工具为各种类型的内存泄漏提供了一种检测方法。


2.原理


kmemleak(kernel memory leak detector)是检测内核空间的内存泄漏的调试工具。检测对象是memblock_allockmallocvmallockmem_cache_alloc等函数分配的内存块,该内存块由struct kmemleak_object来描述(简称为object)kmemleak的实现原理非常简单,通过暴力扫描内存(假定内存中存放的都是指针,以ARM64为例,每次扫描8个字节),如果找不到指向起始地址或者内存块任何位置的指针,则分配的内存块被认为是孤立的。这意味着内核可能无法将分配内存块的地址传递给释放函数,因此该内存块被视为内存泄漏。内存块(object)有3种颜色,分别为黑色、白色、灰色, 通过count和min_count区分不同颜色的object。


黑色: min_count = -1,表示被忽略的object,此object不包含对别人的引用,也不会存在内存泄漏,比如代码段会标记为黑色。


白色: count < min_count,孤立的object,没有足够的引用指向这个object,一轮扫描结束后被认为泄漏的内存块。


灰色: min_count = 0,表示不是孤立的object,即不存在内存泄漏的object,如代码中主动标记object为灰色,防止误报(如data、bss、ro_after_init)。或者count >= min_count,对该object有足够的指针引用,认为不存在内存泄漏的内存块。


具体检测步骤如下:


  • 1、通过struct kmemleak_object(简称为object)描述kmallocvmallockmem_cache_alloc等函数申请的内存块,记录申请内存的起始地址,大小、call trace等信息。同时把object加入到红黑树object_tree_root和双向链表object_list中,红黑树中的key值为内存块的起始地址。


  • 2、遍历双向链表object_list,把所有的objectcount计数清0,即在新的一轮扫描前,尽可能的把能复位成白色的object标记为白色。然后判断object是否是灰色(默认databssro_after_init段会被标记为灰色),如果是灰色的object则把object加入到灰色链表gray_list中。


  • 3、扫描内存中可能存放指针的内存区域(per-cpu段、struct page的内容、内核栈、灰色链表),根据挂在红黑树中所有的object的地址范围进行对比。如果有指针指向某一个object(指向该object的起始地址或者指向object地址范围内),会把object对应的count字段增加1,如果object变成灰色,则会把object加入到灰色链表中。


  • 4、扫描object_list中的白色对象的object,判断object所描述的地址范围的内容的crc值是否发生变化,如果发生变化,则同样把object加入到灰色链表gray_list中。说明通过间接的方式访问了object描述的地址范围,不是内存泄漏,减少误报。


  • 5、重新扫描灰色链表,因为步骤4中,可能有些白色的object加入到了灰色链表中,需要重新扫描。


  • 6、经过上述一系列的扫描,剩余白色的object就是可疑的内存泄漏点。 

3.数据结构


3.1、kmemleak_object


struct kmemleak_object描述一段通过memblock_allockmallocvmallockmem_cache_alloc等函数分配的内存块。此内存块会加入到红黑树object_tree_root和双向链表object_list中。


struct kmemleak_object {    raw_spinlock_t lock;    unsigned int flags;         struct list_head object_list;    struct list_head gray_list;    struct rb_node rb_node;         atomic_t use_count;    unsigned long pointer;    size_t size;    unsigned long excess_ref;    int min_count;    int count;    u32 checksum;    struct hlist_head area_list;    unsigned long trace[MAX_TRACE];    unsigned int trace_len;    unsigned long jiffies;      /* creation timestamp */    pid_t pid;          /* pid of the current task */    char comm[TASK_COMM_LEN];   /* executable name */};



lockspinlock锁用于保护当前的object对象。


flagsobject的状态标志位。有以下状态标志位:


  • OBJECT_ALLOCATED:表示已经分配的内存块的状态标志。在创建object的时候,会置上此标记,在释放object的时候,清除此标记。


  • OBJECT_REPORTED:表示经过一轮内存扫描之后,把有内存泄漏风险object的flags置上OBJECT_REPORTED,然后用户可以通过cat /sys/kernel/debug/kmemleak获取有内存泄漏风险的object。


  • OBJECT_NO_SCAN:表示不去扫描此内存块。kmemleak为了减少误报和漏报,通过封装好的接口设置内存块是否需要扫描,如果不需要扫描则flags置上OBJECT_NO_SCAN标志。


  • OBJECT_FULL_SCAN:表示当内存不足分配scan_area失败的时候,把当前的object标记为OBJECT_FULL_SCAN,表示此objcet全部扫描,不再是局部扫描


object_list:通过该字段把objec添加到object_list链表中。


gray_list:通过该字段把object添加到gray_list链表中。


rb_node:通过该字段把object添加到object_tree_root的红黑树中。


use_count:object使用计数。通过get_object增加计数,put_object减少计数,当use_count = 0时释放该object。


pointer:object的起始地址。


size:object的大小。


excess_ref:具体见kmemleak_vmalloc函数实现。


min_count:指向内存块的最少指针个数。如果小于该值,说明有内存泄漏的嫌疑。


count:扫描到的指向内存块的指针总数,和min_count配合使用。


checksum:内存块的CRC校验和。


area_list:如果area_list链表为NULL,则以object的pointer为起始地址和size为大小的地址范围扫描。如果不为NULL,以area_list链表中的kmemleak_scan_area节点的start和size为地址范围扫描。一个object描述的内存块可能被分割为多个kmemleak_scan_area区域,所有的kmemleak_scan_area通过node节点添加到area_list为头的链表中。


trace:保存创建object的stack trace的地址。


trace_len:表示stack trace的实际深度,最大深度为MAX_TRACE(16)。


jiffies:创建object时的jiffies。


pid:表示创建objcet的pid号。


comm:创建object的进程名。


3.2、kmemleak_scan_area


struct kmemleak_scan_area内存块的扫描区域描述符。为了降低误报,限制所属的object描述的内存块的扫描范围,对object描述的地址范围划分为不同的kmemleak_scan_area区域进行扫描。


/* scanning area inside a memory block */struct kmemleak_scan_area {                                                                                                                                                    struct hlist_node node;    unsigned long start;    size_t size;};


3.3、全局变量


object_list:新创建的object会挂入到全局的objcet_list链表中。


gray_list:如果object不存在内存泄漏的风险,会把object加入到gray_list链表中,表示不存在内存泄漏风险的object。


object_tree_root:为了加快查询速度,新创建的object,不仅会加入到object_list全局链表中,同时会加入到object_tree_root为根的红黑树,红黑树的key值为object的起始地址。


min_addr:所有object中最小的起始地址。有可能最小起始地址的object已经不在object链表中或者红黑树中。目的是为了对检测的地址进行简单的过滤。


max_addr:所有object中最大的结束地址。有可能最大结束地址的object已经不在object链表中或者红黑树中。目的是为了对检测的地址进行简单的过滤。


jiffies_last_scan:开始扫描时候的jiffies。


jiffies_min_age:为了减少误报,避免报告最近分配的object。因为最近分配的object的指针有可能临时存放在cpu的寄存器中。默认值为MSECS_MIN_AGE(5s)。通过unreferenced_object函数可以看出上报有内存泄漏风险的object,需要在此扫描周期开始的T0之前创建object。而T0之后到扫描结束之间创建的object,要在下一个周期进行扫描检测。



static bool unreferenced_object(struct kmemleak_object *object){    return (color_white(object) && object->flags & OBJECT_ALLOCATED) &&        time_before_eq(object->jiffies + jiffies_min_age,                                                                                                                              jiffies_last_scan);}

jiffies_scan_wait:两次扫描的时间间隔SECS_SCAN_WAIT默认为60s。


4.kmemleak代码实现


4.1、kmemleak_init


void __init kmemleak_init(void){#ifdef CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF    if (!kmemleak_skip_disable) { /* 1 */        kmemleak_disable();        return;    }#endif    /* register the data/bss sections */ /* 2 */    create_object((unsigned long)_sdata, _edata - _sdata,              KMEMLEAK_GREY, GFP_ATOMIC);    create_object((unsigned long)__bss_start, __bss_stop - __bss_start,              KMEMLEAK_GREY, GFP_ATOMIC);    /* only register .data..ro_after_init if not within .data */    if (&__start_ro_after_init < &_sdata || &__end_ro_after_init > &_edata)        create_object((unsigned long)__start_ro_after_init,                  __end_ro_after_init - __start_ro_after_init,                  KMEMLEAK_GREY, GFP_ATOMIC);}


  • 1、如果定义了CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF宏或者通过cmdline设置为kmemleak=off则默认关闭kmemleak。如果cmdline中设置kmemleak=on则表示默认开启kmemleak功能。如果没有定义CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF宏,则默认是开启kmemleak功能。


  • 2、创建data段、bss段、.data..ro_after_init段对应的object


思考


问题一为什么不直接静态扫描这些段的内容,而是需要通过object的方式进行管理?


:因为这些section的某些区域可能被动态的释放(如bss段),如果静态扫描可能产生page fault,进一步产生kenrel panic。所以这里采用创建object的方式去扫描bss段,同时把此object标记为灰色,因为这个object描述的内存块不存在内存泄漏。当需要释放bss段的某些区域的时候通过调用kmemleak_free_part函数动态的把bss段进行分割成不同的新的object。(扣除释放的区域)


问题二:为什么需要判断.data..ro_after_init段的范围?


:.data..ro_after_init段表示在内核初始化过程中这个段是可读写的,在初始化完成之后把该段修改为只读。不同的架构的.data..ro_after_init段位于不同的区域,有的直接属于data段,有些会归到rodata段中。如果在data段里,则无需再创建object,如果不在data段内,则需要创建对应的object。


4.2、create_object

 



创建一个object对象,并object的成员进行初始化,同时把object加入到红黑树和双向链表中。假设新创建的object起始地址为10,如下图所示:

 


4.3、delete_object_full/delete_object_part


 

delete_object_full删除整个object,把object从红黑树中和双向链表中删除,同时释放object对应的内存。


 

delete_object_part切割object对象,把完整的object进行切割,有4种情况:


  • 1、左边删除,只留右边的区域,以右边区域为内存块,创建一个新的object

  • 2、右边删除,只留左边的区域,以左边区域为内存块,创建一个新的object

  • 3、刚好完全删除整个object描述的区域,等价于delete_object_full

  • 4、删除中间区域,留两边区域,创建两个新的object

 


put_object递减object的引用计数,如果引用计数为0,则把object进行释放。


4.4、创建object的api接口分析


api接口函数

分析

kmemleak_alloc

kmemleak_alloc直接调用create_object函数,ptr、size、min_count由使用者指,如kmalloc、slab/slub/slob函数。min_count为1,表示至少有一处指针指向申请的内存块。

kmemleak_alloc_percpu

kmemleak_alloc_percpu函数需要对每个cpu都调用一次create_object函数,其中min_count为0,表示percpu区域的内存不存在内存泄漏,即默认为灰色object。

kmemleak_vmalloc

kmemleak_vmalloc函数首先调用create_object创建一个新的object,但min_count为2,即表示最少有两处指针指向内存块才能说明vmalloc申请的内存块没有产生泄漏。同时把area->addr设置到object->excess_ref字段中。

kmemleak_alloc_phys

kmemleak_alloc_phys函数的起始地址为物理地址,主要用于memblock机制中memblock_alloc申请的内存块。且min_count为0,表示memblock_alloc申请的内存块默认为灰色object,不存在内存泄漏,只对内存块内容扫描。


思考:


1、kmemleak_vmalloc中为什么min_count等于2?

 


从图中我们可以看出,struct vm_struct中的addr字段指向vmalloc申请的内存块,strct vmap_area中的va_start字段也指向了vmalloc申请的内存块。同时我们可以知道vmalloc的返回值肯定也保存在某个变量中。理论上至少有3处指针指向了vmalloc的内存块的起始地址,为什么min_count为2?因为strct vmap_area中va_start字段在alloc_vmap_area函数中通过kmemleak_scan_area(&va->rb_node, SIZE_MAX, gfp_mask)函数给过滤掉了,所以min_count为2。


2、kmemleak_vmalloc中为什么要把area->addr设置到vm_struct内存块对应的object的excess_ref字段中?


答:考虑这样一种场景,vmalloc申请的内存块的起始地址,并没有被直接引用,而是通过一个全局指针struct vm_struct *tmp 间接引用。我们可以得到如下信息:


1、tmp可以通过vm_struct间接的访问vmalloc的区域。

2、vm_struct的指针同时也被保存在vmap_area中。

通过上面信息我们可以知道扫描全局指针tmp的时候会把vm_struct内存块对应的object加入到灰色链表中。扫描vmap_area的时候遍历到vm_struct指针的时候,发现指针对应的object已经加入到灰色链表中,不做处理,然后在扫描vm_struct所在内存块对应的object的灰色链表的时候,扫描到addr字段的时候,把addr对应的vmalloc区域的object的count++。此时count 1) < min_count2)会报内存泄漏。其实不是内存泄漏,因为我们可以通过tmp指针间接的找到vmalloc的addr。所以如果我们发现vm_struct对应的object已经变为灰色了,我们需要确定下vm_struct中addr字段是否在红黑树中能找到对应的object?如果能找到,则把addr对应的object的count++。因此对于vmalloc申请的区域,我还需要检查对vm_struct引用次数。如果大于等于2次,我们也不认为是内存泄漏。


4.5、 kmemleak_scan_thread


kmemleak_scan_thread函数实现,整个扫描流程的逻辑见下面流程图:



 

4.6、scan_gray_list


scan_gray_list扫描灰色链表。

 


  • 1、从灰色链表中获取一个object


  • 2、如果object对应的灰色链表不为NULL,则扫描当前的object,扫描完成后,获取下一个object,然后把当前的object从灰色链表中删除,同时递减引用计数,因为在加入灰色链表的时候会调用get_object增加引用计数。


4.7、scan_object


scan_object扫描object的内容。

 


  • 1、如果object的flags中OBJECT_NO_SCAN被置位了,则不去扫描此object对应的内存块。kmemleak_not_leak、kmemleak_ignore等函数会把object的flags置上OBJECT_NO_SCAN,无需扫描此object的内容,可防止误报。


  • 2、如果object已经被释放了,自然也不能扫描。


  • 3、如果object->area_listNULL或者OBJECT_FULL_SCAN被置位,说明object的内存块内容需要被全部扫描。


  • 4、如果object->area_list不为NULL且OBJECT_FULL_SCAN未置位,则扫描object区域的部分内容,只扫描添加到object->area_list中指定的区域(通过kmemleak_scan_area函数指定object内存块的地址扫描范围)。


4.8、scan_block


scan_block扫描指定内存地址范围内容。


 

  • 1、如果扫描的指针不在最大最小值范围内,则跳过此指针。

  • 2、在红黑树中查找是否有满足条件的object,条件为pointer在[object->pointer, object->pointer + size)范围内,如果有则返回对应的object。


  • 3、如果没找到,则跳过此指针。

  • 4、如果pointer指针找到的object是自己,则也跳过此指针。

  • 5、如果已经是灰色的object就不再更新。同时获取object的excess_ref字段,这个字段主要用于vmalloc场景。

  • 6、如果不是灰色的object,则更新object。如果是白色,则对object的count++。如果变成灰色,则增加引用计数同时把object添加到灰色链表中。

  • 7、用于vmalloc场景,通过vm_struct间接访问vmalloc的返回地址。经过扫描发现指针指向的内存块对应的object为vm_struct区域且此object已经变成灰色,则需要检查vm_struct中addr对应的内存块是否在红黑树中,如果在,则需要把addr对应内存块的object的count++。如果变成灰色,则增加引用计数同时把addr对应的object添加到灰色链表中,防止因引用了vm_struct而产生的误报。


5.false positives/negatives


5.1、false positives(误报)


误报不是内存泄漏,而报告为内存泄漏。

可能产生误报的原因:


  • 1、通过固定偏移映射的方式访问虚拟地址。如kasan_module_alloc函数对影子区域的内存块的申请是通过__vmalloc_node_range,而使用是通过非影子区的地址来访问,即通过kasan_mem_to_shadow(addr)函数获取影子区址间接访问。这时候需要通过kmemleak_ignore函数告诉kmemleak这不是内存泄漏。同时kmemleak_ignore还能保证影子区的内容不会被扫描,因为影子区域并不存放指针。


include/linux/kasan.hstatic inline void *kasan_mem_to_shadow(const void *addr){return (void *)((unsigned long)addr >> KASAN_SHADOW_SCALE_SHIFT)    + KASAN_SHADOW_OFFSET;}


  • 2、没有保存虚拟地址而保存物理地址或者struct page等。


如hsc_msg_alloc函数,保存的是buf对应的page。virt_to_page(buf)


drivers/hsi/clients/hsi_char.cstatic inline struct hsi_msg *hsc_msg_alloc(unsigned int alloc_size)                                                                                                {    void *buf;    buf = kmalloc(alloc_size, GFP_KERNEL);    sg_init_one(msg->sgt.sgl, buf, alloc_size);     /* Ignore false positive, due to sg pointer handling */    kmemleak_ignore(buf);    return msg;}sg_init_onesg_set_buf(sg, buf, buflen)sg_set_page(sg,virt_to_page(buf), buflen,offset_in_page(buf))


  • 3、没有直接保存虚拟地址而是保存虚拟地址或上某个变量。


arch/s390/kernel/nmi.cstatic int __init nmi_init(void){    unsigned long origin, cr0, size;  ...    origin = (unsigned long) kmem_cache_alloc(mcesa_cache, GFP_KERNEL);                                                                                                 kmemleak_not_leak((void *) origin);  ...    S390_lowcore.mcesad = origin | mcesa_origin_lc;  ...return 0;}


  • 4、指针存放的区域不会被扫描,如vmap函数映射的区域,没有对应的object


kernel/bpf/ringbuf.cstatic struct bpf_ringbuf *bpf_ringbuf_area_alloc({pages = bpf_map_area_alloc(array_size, numa_node);...rb = vmap(pages, nr_meta_pages + 2 * nr_data_pages,      VM_ALLOC | VM_USERMAP, PAGE_KERNEL);kmemleak_not_leak(pages);rb->pages = pages;...}


  • 5、其他情况。


综上可以看出产生误报的原因是没有直接保存申请出来的虚拟地址,而是

保存虚拟地址某种映射关系得到的值,或者存放指针的内存块无法被

扫描(如vmap区域),而产生误报。


如何解决误报?


可以通过kmemleak_ignorekmemleak_not_leak等函数显示告诉kmemleak这不是内存泄漏。kmemleak_ignore表示object不存在内存泄漏,且也不会扫描内存块的内容。kmemleak_not_leak表示object不存在内存泄漏,但是会扫描内存块的内容。


5.2、false negatives(漏报)


漏报是内存泄漏,但是没有报告出来。

比如扫描的地址存放的是数据而不是指针,但是能在红黑树中找到对应的

object,并把此object加入到灰色链表中,这样就产生了漏报。


如何解决漏报?


可以通过kmemleak_ignore、 kmemleak_scan_area kmemleak_no_scan and kmemleak_erase函数解决漏报问题,不同场景使用不同的函数。


6.使用方法


使用kmemleak可以很方便地检测出内核态的内存泄露。可以用于设备驱动程序或内核模块的评估。虽然kmemleak的扫描算法存在漏报和误报的可能,但是并不影响我们的使用。因为这个工具的目的是为了给我们进一步分析提供线索,并不需要绝对精确,小概率的误报和漏报并不影响这个工具的实用性。


6.1、常用功能宏


内容

CONFIG_DEBUG_KMEMLEAK

在kernel hacking中打开CONFIG_DEBUG_KMEMLEAK宏,表示内核支持kmemleak功能。

CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN

如果开启CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN宏,则会触发自动扫描,调用start_scan_thread函数进行扫描。

CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF

如果定义了CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF宏或者通过cmdline设置为kmemleak=off,则默认关闭kmemleak。如果cmdline中设置kmemleak=on,则表示默认开启kmemleak功能。如果没有定义CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF宏,则默认是开启kmemleak功能。


6.2、具体使用方法


  • 1、挂载debugfs

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


  • 2、内核线程每10分钟(默认情况下)扫描一次,并打印找到的可疑的内存泄漏object。也可以在任意时刻执行kmemleak的内存扫描。

echo scan > /sys/kernel/debug/kmemleak


  • 3、详细的输出信息通过/sys/kernel/debug/kmemleak获取。

cat /sys/kernel/debug/kmemleak


6.3、其它参数说明


参数

内容

off

禁用kmemleak。不再跟踪内存分配和释放。一旦禁用,就不能再次开启。

stack=on

启用线程栈区域的扫描。默认是on。

stack=off

禁用线程栈区域的扫描。

scan=on

开启kmemleak内核线程的自动扫描。默认为on。

scan=off

停止kmemleak内核线程的自动扫描。

scan=

设置kmemleak线程执行扫描时间间隔。单位为秒,默认为600s(10分钟)。0s表示停止自动扫描。

scan

手动触发扫描,立即扫描。

clear

清除检测出的数据,即清除之前判断为内存泄露的object信息,会把这些object标记为KMEMLEAK_GREY,并不会把object从红黑树和双向链表中删除,不在/sys/kernel/debug/kmemleak中显示,只是不显示,可以使用dump参数进行确定。在使用kmemleak前清除没有关系的信息时使用。

dump=

显示addr对应object信息。


详细的使用方法参考kenrel文档Documentation/dev-tools/kmemleak.rst。


7.案例


从kmemleak.rst文档中摘取的log。


        # cat /sys/kernel/debug/kmemleak        unreferenced object 0xffff89862ca702e8 (size 32):          comm "modprobe", pid 2088, jiffies 4294680594 (age 375.486s)          hex dump (first 32 bytes):            6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk            6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b a5  kkkkkkkkkkkkkkk.          backtrace:            [<00000000e0a73ec7>] 0xffffffffc01d2036            [<000000000c5d2a46>] do_one_initcall+0x41/0x1df            [<0000000046db7e0a>] do_init_module+0x55/0x200            [<00000000542b9814>] load_module+0x203c/0x2480            [<00000000c2850256>] __do_sys_finit_module+0xba/0xe0            [<000000006564e7ef>] do_syscall_64+0x43/0x110            [<000000007c873fa6>] entry_SYSCALL_64_after_hwframe+0x44/0xa9


通过kmemleak report的输出信息,我们可以获取如下信息:


  • 1、产生泄漏内存块对应的object的起始地址为0xffff89862ca702e8,

泄漏的大小为32个字节。


  • 2、进程名为modprobepid为2088,创建object时的jiffies为375.486s。

  • 3、泄漏内存块的前32字节数据。

  • 4、泄漏点的backtrace信息。

 


Linux阅码场 专业的Linux技术社区和Linux操作系统学习平台,内容涉及Linux内核,Linux内存管理,Linux进程管理,Linux文件系统和IO,Linux性能调优,Linux设备驱动以及Linux虚拟化和云计算等各方各面.
评论 (0)
  • 文/郭楚妤编辑/cc孙聪颖‍越来越多的企业开始蚕食动力电池市场,行业“去宁王化”态势逐渐明显。随着这种趋势的加强,打开新的市场对于宁德时代而言至关重要。“我们不希望被定义为电池的制造者,而是希望把自己称作新能源产业的开拓者。”4月21日,在宁德时代举行的“超级科技日”发布会上,宁德时代掌门人曾毓群如是说。随着宁德时代核心新品骁遥双核电池的发布,其搭载的“电电增程”技术也走进业界视野。除此之外,经过近3年试水,宁德时代在换电业务上重资加码。曾毓群认为换电是一个重资产、高投入、长周期的产业,涉及的利
    华尔街科技眼 2025-04-28 21:55 181浏览
  • 4月22日下午,备受瞩目的飞凌嵌入式「2025嵌入式及边缘AI技术论坛」在深圳深铁皇冠假日酒店盛大举行,此次活动邀请到了200余位嵌入式技术领域的技术专家、企业代表和工程师用户,共享嵌入式及边缘AI技术的盛宴!1、精彩纷呈的展区产品及方案展区是本场活动的第一场重头戏,从硬件产品到软件系统,从企业级应用到高校教学应用,都吸引了现场来宾的驻足观看和交流讨论。全产品矩阵展区展示了飞凌嵌入式丰富的产品线,从嵌入式板卡到工控机,从进口芯片平台到全国产平台,无不体现出飞凌嵌入式在嵌入式主控设备研发设计方面的
    飞凌嵌入式 2025-04-28 14:43 170浏览
  • 一、智能家居的痛点与创新机遇随着城市化进程加速,现代家庭正面临两大核心挑战:情感陪伴缺失:超60%的双职工家庭存在“亲子陪伴真空期”,儿童独自居家场景增加;操作复杂度攀升:智能设备功能迭代导致用户学习成本陡增,超40%用户因操作困难放弃高阶功能。而WTR096-16S录音语音芯片方案,通过“语音交互+智能录音”双核驱动,不仅解决设备易用性问题,更构建起家庭成员间的全天候情感纽带。二、WTR096-16S方案的核心技术突破1. 高保真语音交互系统动态情绪语音库:支持8种语气模板(温柔提醒/紧急告警
    广州唯创电子 2025-04-28 09:24 191浏览
  •  探针台的维护直接影响其测试精度与使用寿命,需结合日常清洁、环境控制、定期校准等多维度操作,具体方法如下:一、日常清洁与保养1.‌表面清洁‌l 使用无尘布或软布擦拭探针台表面,避免残留清洁剂或硬物划伤精密部件。l 探针头清洁需用非腐蚀性溶剂(如异丙醇)擦拭,检查是否弯曲或损坏。2.‌光部件维护‌l 镜头、观察窗等光学部件用镜头纸蘸取wu水jiu精从中心向外轻擦,操作时远离火源并保持通风。3.‌内部防尘‌l 使用后及时吹扫灰尘,防止污染物进入机械滑
    锦正茂科技 2025-04-28 11:45 118浏览
  • 贞光科技代理品牌紫光国芯的车规级LPDDR4内存正成为智能驾驶舱的核心选择。在汽车电子国产化浪潮中,其产品以宽温域稳定工作能力、优异电磁兼容性和超长使用寿命赢得市场认可。紫光国芯不仅确保供应链安全可控,还提供专业本地技术支持。面向未来,紫光国芯正研发LPDDR5车规级产品,将以更高带宽、更低功耗支持汽车智能化发展。随着智能网联汽车的迅猛发展,智能驾驶舱作为人机交互的核心载体,对处理器和存储器的性能与可靠性提出了更高要求。在汽车电子国产化浪潮中,贞光科技代理品牌紫光国芯的车规级LPDDR4内存凭借
    贞光科技 2025-04-28 16:52 282浏览
  • 在电子电路设计和调试中,晶振为电路提供稳定的时钟信号。我们可能会遇到晶振有电压,但不起振,从而导致整个电路无法正常工作的情况。今天凯擎小妹聊一下可能的原因和解决方案。1. 误区解析在硬件调试中,许多工程师在测量晶振时发现两端都有电压,例如1.6V,但没有明显的压差,第一反应可能是怀疑短路。晶振电路本质上是一个交流振荡电路。当晶振未起振时,两端会静止在一个中间电位,通常接近电源电压的一半。万用表测得的是稳定的直流电压,因此没有压差。这种情况一般是:晶振没起振,并不是短路。2. 如何判断真
    koan-xtal 2025-04-28 05:09 261浏览
  • 随着电子元器件的快速发展,导致各种常见的贴片电阻元器件也越来越小,给我们分辨也就变得越来越难,下面就由smt贴片加工厂_安徽英特丽就来告诉大家如何分辨的SMT贴片元器件。先来看看贴片电感和贴片电容的区分:(1)看颜色(黑色)——一般黑色都是贴片电感。贴片电容只有勇于精密设备中的贴片钽电容才是黑色的,其他普通贴片电容基本都不是黑色的。(2)看型号标码——贴片电感以L开头,贴片电容以C开头。从外形是圆形初步判断应为电感,测量两端电阻为零点几欧,则为电感。(3)检测——贴片电感一般阻值小,更没有“充放
    贴片加工小安 2025-04-29 14:59 251浏览
  • 晶振在使用过程中可能会受到污染,导致性能下降。可是污染物是怎么进入晶振内部的?如何检测晶振内部污染物?我可不可以使用超声波清洗?今天KOAN凯擎小妹将逐一解答。1. 污染物来源a. 制造过程:生产环境不洁净或封装密封不严,可能导致灰尘和杂质进入晶振。b. 使用环境:高湿度、温度变化、化学物质和机械应力可能导致污染物渗入。c. 储存不当:不良的储存环境和不合适的包装材料可能引发化学物质迁移。建议储存湿度维持相对湿度在30%至75%的范围内,有助于避免湿度对晶振的不利影响。避免雨淋或阳光直射。d.
    koan-xtal 2025-04-28 06:11 154浏览
  • 浪潮之上:智能时代的觉醒    近日参加了一场课题的答辩,这是医疗人工智能揭榜挂帅的国家项目的地区考场,参与者众多,围绕着医疗健康的主题,八仙过海各显神通,百花齐放。   中国大地正在发生着激动人心的场景:深圳前海深港人工智能算力中心高速运转的液冷服务器,武汉马路上自动驾驶出租车穿行的智慧道路,机器人参与北京的马拉松竞赛。从中央到地方,人工智能相关政策和消息如雨后春笋般不断出台,数字中国的建设图景正在智能浪潮中徐徐展开,战略布局如同围棋
    广州铁金刚 2025-04-30 15:24 230浏览
  • 在智能硬件设备趋向微型化的背景下,语音芯片方案厂商针对小体积设备开发了多款超小型语音芯片方案,其中WTV系列和WT2003H系列凭借其QFN封装设计、高性能与高集成度,成为微型设备语音方案的理想选择。以下从封装特性、功能优势及典型应用场景三个方面进行详细介绍。一、超小体积封装:QFN技术的核心优势WTV系列与WT2003H系列均提供QFN封装(如QFN32,尺寸为4×4mm),这种封装形式具有以下特点:体积紧凑:QFN封装通过减少引脚间距和优化内部结构,显著缩小芯片体积,适用于智能门铃、穿戴设备
    广州唯创电子 2025-04-30 09:02 277浏览
  • 文/Leon编辑/cc孙聪颖‍2023年,厨电行业在相对平稳的市场环境中迎来温和复苏,看似为行业增长积蓄势能。带着对市场向好的预期,2024 年初,老板电器副董事长兼总经理任富佳为企业定下双位数增长目标。然而现实与预期相悖,过去一年,这家老牌厨电企业不仅未能达成业绩目标,曾提出的“三年再造一个老板电器”愿景,也因市场下行压力面临落空风险。作为“企二代”管理者,任富佳在掌舵企业穿越市场周期的过程中,正面临着前所未有的挑战。4月29日,老板电器(002508.SZ)发布了2024年年度报告及2025
    华尔街科技眼 2025-04-30 12:40 233浏览
  • 在CAN总线分析软件领域,当CANoe不再是唯一选择时,虹科PCAN-Explorer 6软件成为了一个有竞争力的解决方案。在现代工业控制和汽车领域,CAN总线分析软件的重要性不言而喻。随着技术的进步和市场需求的多样化,单一的解决方案已无法满足所有用户的需求。正是在这样的背景下,虹科PCAN-Explorer 6软件以其独特的模块化设计和灵活的功能扩展,为CAN总线分析领域带来了新的选择和可能性。本文将深入探讨虹科PCAN-Explorer 6软件如何以其创新的模块化插件策略,提供定制化的功能选
    虹科汽车智能互联 2025-04-28 16:00 203浏览
  • 网约车,真的“饱和”了?近日,网约车市场的 “饱和” 话题再度引发热议。多地陆续发布网约车风险预警,提醒从业者谨慎入局,这背后究竟隐藏着怎样的市场现状呢?从数据来看,网约车市场的“过剩”现象已愈发明显。以东莞为例,截至2024年12月底,全市网约车数量超过5.77万辆,考取网约车驾驶员证的人数更是超过13.48万人。随着司机数量的不断攀升,订单量却未能同步增长,导致单车日均接单量和营收双双下降。2024年下半年,东莞网约出租车单车日均订单量约10.5单,而单车日均营收也不容乐
    用户1742991715177 2025-04-29 18:28 236浏览
  • 你是不是也有在公共场合被偷看手机或笔电的经验呢?科技时代下,不少现代人的各式机密数据都在手机、平板或是笔电等可携式的3C产品上处理,若是经常性地需要在公共场合使用,不管是工作上的机密文件,或是重要的个人信息等,民众都有防窃防盗意识,为了避免他人窥探内容,都会选择使用「防窥保护贴片」,以防止数据外泄。现今市面上「防窥保护贴」、「防窥片」、「屏幕防窥膜」等产品就是这种目的下产物 (以下简称防窥片)!防窥片功能与常见问题解析首先,防窥片最主要的功能就是用来防止他人窥视屏幕上的隐私信息,它是利用百叶窗的
    百佳泰测试实验室 2025-04-30 13:28 378浏览
  • 一、gao效冷却与控温机制‌1、‌冷媒流动设计‌采用低压液氮(或液氦)通过毛细管路导入蒸发器,蒸汽喷射至样品腔实现快速冷却,冷却效率高(室温至80K约20分钟,至4.2K约30分钟)。通过控温仪动态调节蒸发器加热功率,结合温度传感器(如PT100铂电阻或Cernox磁场不敏感传感器),实现±0.01K的高精度温度稳定性。2、‌宽温区覆盖与扩展性‌标准温区为80K-325K,通过降压选件可将下限延伸至65K(液氮模式)或4K(液氦模式)。可选配475K高温模块,满足材料在ji端温度下的性能测试需求
    锦正茂科技 2025-04-30 13:08 285浏览
我要评论
0
11
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦