kmalloc 分配实际上不是连续的吗?

Is kmalloc allocation not virtually contiguous?

提问人:md.jamal 提问时间:9/2/2019 最后编辑:John Kugelmanmd.jamal 更新时间:11/7/2023 访问量:560

问:

我发现它返回了物理和几乎连续的记忆。kmalloc

我写了一些代码来观察这种行为,但只有物理内存似乎是连续的,而不是虚拟的。我犯了什么错误吗?

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/moduleparam.h>

MODULE_LICENSE("GPL");

static char *ptr;
int alloc_size = 1024;

module_param(alloc_size, int, 0);

static int test_hello_init(void)
{
    ptr = kmalloc(alloc_size,GFP_ATOMIC);
    if(!ptr) {
        /* handle error */
        pr_err("memory allocation failed\n");
        return -ENOMEM;
    } else {
        pr_info("Memory allocated successfully:%p\t%p\n", ptr, ptr+100);
        pr_info("Physical address:%llx\t %llx\n", virt_to_phys(ptr), virt_to_phys(ptr+100));
    }

    return 0;
}

static void test_hello_exit(void)
{
    kfree(ptr);
    pr_info("Memory freed\n");

}

module_init(test_hello_init);
module_exit(test_hello_exit);

dmesg输出:

Memory allocated successfully:0000000083318b28  000000001fba1614
Physical address:1d5d09c00   1d5d09c64
C Linux 内存管理 linux-device-driver

评论

1赞 Trickzter 9/2/2019
我不完全确定这是否是您的问题,但是在探索 linux 内核的过程中,我发现带有 printk 方法的格式说明符 %p 返回了错误的地址。是否确定带有 %p 说明符的pr_info返回有效的指针地址?我的解决方法是将地址转换为无符号的长长并使用 %llx。也许试一试?

答:

13赞 Marco Bonelli 9/2/2019 #1

打印内核指针通常是一个坏主意,因为它基本上意味着将内核地址泄漏到用户空间,因此当使用 in(或类似的宏等)时,内核会尝试保护自己,并且不会打印真实地址。相反,它会为该地址打印不同的哈希唯一标识符。%pprintk()pr_info()

如果确实要打印该地址,可以使用 。%px


来自(网络版git):Documentation/core-api/printk-formats.rst

指针类型

打印时不带说明符扩展名(即朴素)的指针是 哈希处理以在不向用户泄露内核地址的情况下提供唯一标识符 空间。在 64 位计算机上,前 32 位为零。如果您真的想要地址,请参见下文。%p%px

%p    abcdef12 or 00000000abcdef12

然后,稍后如下:

未修改的地址

%px   01234567 or 0123456789abcdef

当您真正想要打印地址时,用于打印指针。请 考虑您是否泄露了有关 在使用 打印指针之前在内存中进行内核布局。 是 在功能上等同于 。 是首选,因为它更 独特的 grep'able。如果将来我们需要修改内核的方式 处理打印指针 能够找到呼叫会很好 网站。%px%px%lx%px%lx


值得一提的是,可以在打印前转换纯指针(格式化为 )的代码可以在这里找到。Linux 6.6 中的调用链为:_printk() → vprintk() → vprintk_default() → vprintk_emit() → vprintk_store() → printk_sprint() → vscnprintf() → vsnprintf() → pointer() → default_pointer() → ptr_to_id ()”。 %p

评论

0赞 md.jamal 9/2/2019
在 Linux 源代码中,它存在于 Documentation/core-api/printk-formats.rst 文件中
0赞 0andriy 3/16/2021
Marco,在网络上它有更好的视野:kernel.org/doc/html/latest/core-api/printk-formats.html
0赞 Marco Bonelli 3/16/2021
@0andriy是的,确实更好,谢谢。
0赞 vmemmap 7/22/2022
你能链接散列内核地址的源代码吗?
0赞 Marco Bonelli 11/7/2023
@vmemmap有点晚了,但完成了:')