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_size page+1page+0x20증가합니다(0x1000).

답변1

구조체 페이지에 대한 포인터는 메모리 주소입니다. 예를 들어. 0x00a0000. page+10x00a0020과 같은 다른 주소입니다.

그런 다음 이 함수는 0x00a000에서 0x00a0020까지 모든 "잠재적인" 메모리 포인터를 검색합니다. struct page포인터가 특정 방식으로 정렬되어 있다고 가정하는 것 외에는 형식에 대해 아무것도 모릅니다.

관련 정보