解决物理内存无法映射到用户空间

  • 内核(驱动)里__get_free_pages()申请物理页面
  • 用户空间mmap文件/dem/mem的偏移X处到自己进程空间,对其操作 
  • /dev/mem是系统物理内存镜像文件,文件偏移X即内存的偏移X 
  • 内核(驱动)向设备文件比如/dev/video1写一定格式的数据 
  • 用户空间mmap文件/dev/video1到进程空间,去读写

一、mmap简介

对于mmap网络上有很多介绍的资料,我主要用来将物理地址映射到user space的虚拟地址,这样tool才能读取到正确的data。关于mmap的详细介绍可以直接用命令:man mmap看到。

 二、/dev/mem简介

其实以前访问PCI device的MMIO space也是通过打开设备/dev/mem,然后通过mmap映射到user space就可以直接访问。

这里的/dev/mem是整个物理地址空间的映射,之所以是物理地址空间而不是物理内存后面会说明。

访问物理地址的方式如下:

int fd = open("/dev/mem", O_RDWR);        //打开设备

//通过mmap映射物理地址到user space的虚拟地址

virt_addr = mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, physical_addr);

if (virt_addr == MAP_FAILED) {

        //打印出错信息

}

如果mmap出错,那么virt_addr返回(void *) -1,否则就返回映射到的地由于/dev/mem映射的是物理地址空间,所以start设置为NULL,这样offset就可以直接设置成物理地址。

题外话:前面说过访问PCI device的MMIO space也可以通过这种方式访问,但是MMIO register不是在内存条上,而是在PCI device上面,但是由于这些register和内存一样是统一编址,所以最后的物理地址空间是内存条加上各个device的映射到内存地址空间的部分,所以在32-bit操作系统下,也有可能申请到大于4G的地址。

三、问题

在driver中通过alloc_pages申请得到的page,将page的物理地址export到user space,但是user space拿到这个物理地址后并不能mmap成功。通过perror(“mmap”),发现总是返回错误"Operation not permitted!",后来发现是由于kernel对user space访问/dev/mem是有限制的,通过编译选项:CONFIG_STRICT_DEVMEM来限制user space对物理内存的访问,这个选项在文件arch/x86/Kconfig.debug中有说明:

config STRICT_DEVMEM
    bool "Filter access to /dev/mem"
    ---help---
      If this option is disabled, you allow userspace (root) access to all
      of memory, including kernel and userspace memory. Accidental
      access to this is obviously disastrous, but specific access can
      be used by people debugging the kernel. Note that with PAT support
      enabled, even in this case there are restrictions on /dev/mem
      use due to the cache aliasing requirements.

      If this option is switched on, the /dev/mem file only allows
      userspace access to PCI space and the BIOS code and data regions.
      This is sufficient for dosemu and X and all common users of
      /dev/mem.

      If in doubt, say Y.

只有在.config文件中设置CONFIG_STRICT_DEVMEM=n才能获得对整个memory的访问权限,在默认情况下,CONFIG_STRICT_DEVMEM=y,这也就是之前mmap总是报错:“Operation not permitted”的原因。

设置这个选项后,编译kernel,然后运行tool,mmap还是返回错误:“Invalid argument”。后来查到还需要设置编译选项CONFIG_X86_PAT=n,这个选项也是默认开启的,但是要关闭这个选项还需要开启CONFIG_EXPERT,否则CONFIG_X86_PAT总是关不掉。

设置好这三个编译选项后,重新编译kernel,然后运行tool,发现kernel已经解除了对mmap的访问限制,可以正确读取对应物理地址的内容了。

最后还可以通过修改内核源代码来实现,具体的源文件为arch/x86/mm/pat.c(linux-5.4.191),代码如下,修改range_is_allowed直接返回1,转载者本人kernel_hacker为了解决命令busybox devmem 0xxxxxx无法读取host DDR亲测该方法有效:

#ifdef CONFIG_STRICT_DEVMEM
/* This check is done in drivers/char/mem.c in case of STRICT_DEVMEM */
static inline int range_is_allowed(unsigned long pfn, unsigned long size)
{
	return 1;
}
#else
/* This check is needed to avoid cache aliasing when PAT is enabled */
static inline int range_is_allowed(unsigned long pfn, unsigned long size)
{
	u64 from = ((u64)pfn) << PAGE_SHIFT;
	u64 to = from + size;
	u64 cursor = from;

	if (!pat_enabled())
		return 1;

	while (cursor < to) {
		if (!devmem_is_allowed(pfn))
			return 0;
		cursor += PAGE_SIZE;
		pfn++;
	}
	return 1;
}
#endif /* CONFIG_STRICT_DEVMEM */

四、busybox devmem是打开文件/dev/mem进行操作的吗

是的,busybox中的devmem命令是用于对/dev/mem文件进行操作的。/dev/mem是在Linux系统中的一个特殊文件,它代表了整个物理内存空间,可以通过对该文件的读写来直接访问和修改物理内存。通过busybox中的devmem命令,可以在用户空间下操作和修改物理内存的内容,如读取、写入特定的内存地址,进行硬件寄存器的读写等。请注意,在进行这种操作时需要小心,因为对物理内存的错误操作可能导致系统崩溃或数据丢失。 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CPU分页机制是一种用于管理虚拟内存和物理内存映射的技术。它通过将进程的虚拟地址空间划分为固定大小的页,并将每一页映射物理内存中的一个页框上,从而实现虚拟内存和物理内存之间的映射。 具体来说,CPU使用一个叫做页表的数据结构来实现虚拟地址到物理地址的映射。页表中包含了每个虚拟页对应的物理页框号和一些附加信息,例如访问权限等。当进程访问一个虚拟地址时,CPU会先将虚拟地址分解成页号和页内偏移量,然后从页表中查找对应的物理页框号。 如果页表中没有找到对应的映射关系,就会发生缺页异常,并且操作系统会将相应的物理页装入内存。一旦物理页被装入内存,CPU会将页表中的映射关系更新,以便下次访问时可以直接访问物理页。 虚拟内存和物理内存之间的映射关系可以通过多种方式实现,例如: 1. 固定分区映射:将物理内存分为若干个固定大小的分区,每个分区对应一个虚拟内存区域。这种映射方式简单,但是容易造成内存浪费。 2. 可变分区映射:将物理内存按需分配,每个虚拟内存区域映射到一个可变大小的物理内存区域。这种映射方式可以更有效地利用内存空间,但是需要更复杂的管理算法。 3. 页面置换算法:当物理内存不足时,需要通过页面置换算法将一些页面从物理内存中淘汰,以便为新的页面腾出空间。常见的页面置换算法包括LRU、FIFO和随机置换等。 总之,CPU分页机制是一种重要的内存管理技术,它可以实现虚拟内存和物理内存之间的映射,并且通过页面置换算法来管理内存空间

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值