我是 Linux 内核的初学者。现在我正在尝试自己写一个模块来设置页表。
我的电脑是x86,内核版本是5.4.0。
首先我使用内核参数
memmap
保留一些内存,然后我尝试为保留的内存设置页表。
我在代码中使用
pud_alloc
和 include <linux/mm.h>
,但随后我看到此错误:
ERROR: "__pud_alloc" [/root/sun_fs/sunfs.ko] undefined!
ERROR: "init_mm" [/root/sun_fs/sunfs.ko] undefined!
make[2]: *** [scripts/Makefile.modpost:94: __modpost] Error 1
make[1]: *** [Makefile:1670: modules] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-5.4.0-65-generic'
make: *** [Makefile:9: default] Error 2
__pud_alloc
和 init_mm
均未定义。
我发现
__pud_alloc
在/include/linux/mm.h
中声明并在mm/memory.c
中定义。但为什么我用不了呢?
我还有其他方法来手动设置页表吗?
最近我也遇到了类似的问题。我想与用户进程共享内核模块中的一些页面。我的第一个想法是我可以修改用户页表以将这些页面映射到用户虚拟机。
就像你一样,我也遇到过错误
ERROR: "__pud_alloc" [/root/sun_fs/sunfs.ko] undefined!
。为了保证安全,内核没有将这些函数导出给内核模块开发者,令人失望。
但我发现 API
remap_pfn_range()
已导出给开发人员,可以将页面映射到用户虚拟机空间。对我来说非常方便。
static struct page *pages[NPAGES];
static int shmland_mmap(struct file *file, struct vm_area_struct *vma)
{
unsigned long pfn;
int i;
for (i = 0; i < NPAGES; i++) {
pfn = page_to_pfn(pages[i]);
if (remap_pfn_range(vma, vma->vm_start + i * PAGE_SIZE, pfn, PAGE_SIZE, vma->vm_page_prot)) {
return -EAGAIN;
}
}
return 0;
}
我确实希望它可以成为满足您需求的解决方法。