linux支持不带mmu的cpu,virt_to_phys和Linux内核中CPU的MMU之间的关系是什么?

在具有虚拟内存的系统中,OS内核负责建立物理地址和虚拟地址之间的映射。

然而,当CPU执行存取存储器的指令,CPU执行从进程的虚拟地址,表示在内存中的实际位置的物理地址翻译。

您提到的函数可以在内核代码中使用,以获得内核代码中使用的某些地址的虚拟地址到物理地址的转换。例如,对于x86的目标,你可以看到virt_to_phys的定义io.h:

/**

* virt_to_phys - map virtual addresses to physical

* @address: address to remap

*

* The returned physical address is the physical (CPU) mapping for

* the memory address given. It is only valid to use this function on

* addresses directly mapped or allocated via kmalloc.

*

* This function does not give bus mappings for DMA transfers. In

* almost all conceivable cases a device driver should not be using

* this function

*/

static inline phys_addr_t virt_to_phys(volatile void *address)

{

return __pa(address);

}

,如果你遵循的__pa(address)的定义,你会看到,它最终调用__phys_addr其定义为:

unsigned long __phys_addr(unsigned long x)

{

if (x >= __START_KERNEL_map) {

x -= __START_KERNEL_map;

VIRTUAL_BUG_ON(x >= KERNEL_IMAGE_SIZE);

x += phys_base;

} else {

VIRTUAL_BUG_ON(x < PAGE_OFFSET);

x -= PAGE_OFFSET;

VIRTUAL_BUG_ON(!phys_addr_valid(x));

}

return x;

}

因此,您可以看到内核正在使用偏移量从虚拟地址计算物理地址。取决于为翻译编译代码的体系结构会有所不同。正如virt_to_phys的评论所提到的,这只适用于直接映射或通过kmalloc分配的内核内存,它不会将任意物理地址转换为虚拟地址。该翻译依赖于查找页面表映射。

在这两种情况下,作为内核一部分在CPU上执行的实际指令仍然依赖于CPU的MMU从它们操作的虚拟地址转换为数据实际位于内存中的物理地址。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MMIO(Memory Mapped IO)是指通过将设备寄存器映射到系统内存地址空间的方式来进行I/O操作。而虚拟地址是指程序使用的地址,通过MMU(Memory Management Unit)将其转化为对应的物理地址来进行内存访问。 在Linux系统,可以通过/proc文件系统下的/proc/<PID>/maps文件来获取一个物理地址对应的虚拟地址,其<PID>为进程ID。这个文件列出了该进程的虚拟内存映射情况,可以根据物理地址所在的内存区域来确定对应的虚拟地址。 以C语言为例,可以使用mmap函数将物理地址映射到虚拟地址上,具体实现方式如下: ```c #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/mman.h> #define MAP_SIZE 4096UL #define MAP_MASK (MAP_SIZE - 1) int main(int argc, char *argv[]) { int fd; void *map_base, *virt_addr; off_t target; // 打开/dev/mem设备 fd = open("/dev/mem", O_RDWR | O_SYNC); if (fd == -1) { perror("open"); exit(EXIT_FAILURE); } // 计算物理地址对应的偏移量 target = strtoul(argv[1], 0, 0); target &= ~MAP_MASK; // 映射物理地址虚拟地址 map_base = mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target); if (map_base == (void *) -1) { perror("mmap"); exit(EXIT_FAILURE); } // 计算虚拟地址 virt_addr = map_base + (strtoul(argv[1], 0, 0) & MAP_MASK); printf("Physical address: 0x%lx\n", strtoul(argv[1], 0, 0)); printf("Virtual address: 0x%lx\n", (unsigned long) virt_addr); // 解除映射 if (munmap(map_base, MAP_SIZE) == -1) { perror("munmap"); } close(fd); return 0; } ``` 以上代码可以通过命令行参数传入物理地址,然后利用mmap函数将其映射到虚拟地址上,并输出虚拟地址

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值