首先,我有一个可加载的内核模块(LKM),它为字符设备提供了mmap功能.然后用户空间应用程序打开设备并调用mmap LKM在内核模式空间(虚拟高地址)内的LKM堆上分配内存空间.在用户空间侧,数据指针指向虚拟低地址.
下图显示了我如何想象记忆的解剖结构.这是正确的吗?
如果问题不明确,请告诉我,我会尝试添加更多细节.
编辑:图片是关于Gil Hamilton编辑的.黑色箭头现在指向物理地址.
解决方法
内核不需要mmap()来访问用户空间内存.如果用户进程具有内存,则它已根据定义映射到地址空间中.从这个意义上说,内存已经在用户和内核之间共享.
mmap()在用户的虚拟地址空间中创建一个新区域,以便在以后访问时可以通过物理内存填充地址区域.内存的实际分配和修改页表条目是由内核完成的.
mmap()仅对管理虚拟地址空间的用户一半有意义.内核 – 地址空间的一半管理完全不同.
此外,内核半部分由系统中的所有进程共享.每个进程都有其专用的虚拟地址空间,但页面表的编程方式使得内核半部的页表条目对所有进程设置完全相同.
同样,内核没有mmap()来访问用户空间内存. mmap()是内核向用户提供的服务,用于修改用户虚拟地址空间中的当前映射.
首先,内核具有内核地址空间的专用区域(作为其内核空间的一部分),其映射以连续方式存在的整个物理存储器. (在所有64位系统中都是如此.在32位系统中,内核必须“重新映射”以实现此目的.)
其次,如果内核是通过系统调用或异常进入的,而不是通过硬件中断进入的,那么你就拥有了有效的进程上下文,因此内核可以直接“取消引用”用户空间指针来获取正确的值.
第三,如果内核想要在借用的上下文(例如中断处理程序)中执行时依赖于进程的用户空间指针,则内核可以通过遍历vm_area_struct树以获取权限来跟踪进程的虚拟地址,并遍历页表以查找实际的物理页面框架.