Linux中的kmemleak如何检测未引用的内存?

Linux中的kmemleak如何检测未引用的内存?

我正在开发嵌入式 Linux 系统(kernel-5.10.24),我试图了解 kmemleak 是如何工作的。

根据文档,kmemleak扫描数据段,检查是否存在未引用的内存,内核代码如下,

kmemleak_scan()

    /*
     * Struct page scanning for each node.
     */
    get_online_mems();
    for_each_populated_zone(zone) {
        unsigned long start_pfn = zone->zone_start_pfn;
        unsigned long end_pfn = zone_end_pfn(zone);
        unsigned long pfn;

        for (pfn = start_pfn; pfn < end_pfn; pfn++) {
            struct page *page = pfn_to_online_page(pfn);

            if (!page)
                continue;

            /* only scan pages belonging to this zone */
            if (page_zone(page) != zone)
                continue;
            /* only scan if page is in use */
            if (page_count(page) == 0)
                continue;
            scan_block(page, page + 1, NULL);
            if (!(pfn & 63))
                cond_resched();
        }
    }
    put_online_mems();

它获取指向每个 PFN 的指针struct page,并将其传递给scan_block

还有scan_block()

/*
 * Scan a memory block (exclusive range) for valid pointers and add those
 * found to the gray list.
 */
static void scan_block(void *_start, void *_end,
               struct kmemleak_object *scanned)
{
    unsigned long *ptr;
    unsigned long *start = PTR_ALIGN(_start, BYTES_PER_POINTER);
    unsigned long *end = _end - (BYTES_PER_POINTER - 1);
    unsigned long flags;
    unsigned long untagged_ptr;

    raw_spin_lock_irqsave(&kmemleak_lock, flags);
    for (ptr = start; ptr < end; ptr++) {
        struct kmemleak_object *object;
        unsigned long pointer;
        unsigned long excess_ref;

        if (scan_should_stop())
            break;

        kasan_disable_current();
        pointer = *ptr;     ///// ?????
        kasan_enable_current();

        untagged_ptr = (unsigned long)kasan_reset_tag((void *)pointer);
        if (untagged_ptr < min_addr || untagged_ptr >= max_addr)
            continue;

        /*
         * No need for get_object() here since we hold kmemleak_lock.
         * object->use_count cannot be dropped to 0 while the object
         * is still present in object_tree_root and object_list
         * (with updates protected by kmemleak_lock).
         */
        object = lookup_object(pointer, 1);

指向的指针struct page被转换为unsigned long *,并取消引用 ,unsigned long *以获取 来pointer作为要检查的内存地址。

我的困惑来自于取消引用指向 的指针struct page,它是描述 PFN 的结构。为什么解引用可以得到内存地址,而不是结构页呢?

在我的系统中, 的大小struct page为 32 字节,因此page+1page+0x20而不是增加 page_size (0x1000)。

答案1

指向struct page的指针是一个内存地址。例如。 0x00a0000。page+1是另一个地址,比如 0x00a0020。

然后这个函数只是扫描从 0x00a000 到 0x00a0020 的所有“潜在”内存指针。struct page除了假设指针以某种方式对齐之外,它对 的格式一无所知。

相关内容