Linux kernel remap_pfn_range如何将内核内存重新映射到用户空间?

Linux kernel remap_pfn_range如何将内核内存重新映射到用户空间?,linux-kernel,linux-device-driver,kernel-module,virtual-address-space,Linux Kernel,Linux Device Driver,Kernel Module,Virtual Address Space,remap\u pfn\u range函数(用于mmap调用驱动程序)可用于将内核内存映射到用户空间。怎么做的?有人能解释一下精确的步骤吗?内核模式是特权模式(PM),而用户空间是非特权模式(NPM)。在PM中,CPU可以访问所有内存,而在NPM中,某些内存受到限制-CPU无法访问。调用remap\u pfn\u range时,用户空间如何访问仅限于PM的内存范围 查看remap\u pfn\u范围code有pgprot\t结构。这是与保护映射相关的结构。什么是保护映射?这就是上述问题的答案吗?

remap\u pfn\u range
函数(用于
mmap
调用驱动程序)可用于将内核内存映射到用户空间。怎么做的?有人能解释一下精确的步骤吗?内核模式是特权模式(PM),而用户空间是非特权模式(NPM)。在PM中,CPU可以访问所有内存,而在NPM中,某些内存受到限制-CPU无法访问。调用
remap\u pfn\u range
时,用户空间如何访问仅限于PM的内存范围


查看
remap\u pfn\u范围
code有
pgprot\t结构
。这是与保护映射相关的结构。什么是保护映射?这就是上述问题的答案吗?

这真的很简单,内核内存(通常)只是有一个页面表条目,带有特定于体系结构的位,上面写着:“这个页面表条目只有在CPU处于内核模式时才有效”

remap_pfn_range所做的是创建另一个页表条目,将不同的虚拟地址映射到未设置该位的同一物理内存页


通常,这不是一个好主意,顺便说一句:-)

该机制的核心是页表MMU:

或者这个:

以上两幅图片都是x86硬件内存MMU的特征,与Linux内核无关

下面描述了VMAs如何链接到流程的任务结构:


(来源:)

在这里查看函数本身:

内核可以通过内核的PTE访问物理内存中的数据,如下所示:


(来源:)

但是在调用remap_pfn_range()之后,将派生一个PTE(用于现有的内核内存,但将在用户空间中用于访问它)(具有不同的页面保护标志)。进程的VMA内存将被更新,以使用此PTE访问同一内存-从而最大限度地减少复制浪费内存的需要。但是kernel和userspace PTE有不同的属性-用于控制对物理内存的访问,VMA还将在进程级别指定属性:

vma->vm|u flags |=vm|IO | vm|PFNMAP | vm|u dontex和| vm|DONTDUMP


“其中一部分与内核的页表一致,每个进程都不重复”当您这样说时,您的意思是所有进程使用的内核映射只有一个页表副本吗?你能详细说明一下如何做到这一点吗?也许读一下:从图中你可以看到一个进程处理一组页表,其基址将加载到CR3寄存器中。对于要在不同进程之间共享的所有虚拟地址(特别是内核地址),所有这些地址都将具有指向同一物理页的相同值。希望澄清。如何保持“mm信号量”?这个全局变量是每个进程的,但进程内的多个并发线程可能会获取它,因此需要通过up_read()或down_read()进行锁定。