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 pagePFNを記述する構造へのポインタです。逆参照が構造ページの代わりにメモリアドレスを取得できるのはなぜですか?

私のシステムではサイズstruct pageは32バイトなので、代わりにpage_sizepage+1だけpage+0x20を増やします(0x1000)。

答え1

構造体ページへのポインタはメモリアドレスです。例えば。 0x00a0000。page+10x00a0020 などの別のアドレスです。

次に、この関数は、0x00a000から0x00a0020までのすべての「潜在的な」メモリポインタを取得します。struct pageポインタが特定の方法でソートされていると仮定する以外は、フォーマットについて何も知りません。

関連情報