Linux物理地址与虚拟地址简介

        目前, 大多数嵌入式微控制器(如 ARM、 PowerPC 等) 中并不提供 I/O 空间, 而仅存在内存空间。 内存空间可以直接通过地址、 指针来访问, 程序及在程序运行中使用的变量和其他数据都存在于内存空间中。内存地址可以直接由 C 语言指针操作, 例如, 操作一个寄存器, 可以定义一个指针来操作寄存器, 如下所示:
unsighted int *p = 0x12345678;
*p=0x87654321;
        以上程序的意义是在绝对地址 0x12345678(ARM、 PowerPC) 中写入 0x87654321。高性能处理器一般会提供一个内存管理单元(MMU) , 该单元辅助操作系统进行内存管理, 提供虚拟地址和物理地址的映射、 内存访问权限保护和 Cache 缓存控制等硬件支持。 操作系统内核借助 MMU 可以让用户感觉到程序好像可以使用非常大的内存空间, 从而使得编程人员在写程序时不用考虑计算机中物理内存的实际容量。
         MMU 具有虚拟地址和物理地址转换、 内存访问权限保护等功能, 这将使得 Linux 操作系统能单独为系统的每个用户进程分配独立的内存空间并保证用户空间不能访问内核空间的地址, 为操作系统的虚拟内存管理模块提供硬件基础。 上层应用看到的内存都是虚拟内存, 应用就不能直接访问硬件, 所以这样就保证了系统安全。
        对于包含 MMU 的处理器而言, Linux 系统提供了复杂的存储管理系统, 使得进程所能访问的内存达到4GB。 在 Linux 系统中, 进程的 4GB 内存空间被分为两个部分——用户空间与内核空间。 用户空间的地址一般分布为 0~3GB(即 PAGE_OFFSET, 在 0x86 中它等于 0xC0000000) , 这样, 剩下的 3~4GB 为内核空间, 如下图所示。 用户进程通常只能访问用户空间的虚拟地址, 不能访问内核空间的虚拟地址。 用户进程只有通过系统调用(代表用户进程在内核态执行) 等方式才可以访问到内核空间。

        每个进程的用户空间都是完全独立、 互不相干的, 用户进程各自有不同的页表。 而内核空间是由内核负责映射, 它并不会跟着进程改变, 是固定的。 内核空间的虚拟地址到物理地址映射是被所有进程共享的,内核的虚拟空间独立于其他程序。
        MMU 非常复杂, 那么我们如何完成物理地址到虚拟地址的转换呢? 内核给我们提供了相关的函数, 我们先来了解下这些函数。 函数定义在内核源码目录 include/asm-generic/io.h
ioremap: 把物理地址转换成虚拟地址
iounmap: 释放掉 ioremap 映射的地址

函数static inline void __iomem *ioremap(phys_addr_t offset, size_t size)
参数
phys_addr_t
offset
映射物理地址的起始地址
参数 size_t size要映射多大的内存空间
返回值成功返回虚拟地址的首地址失败返回 NULL。
功能把物理地址转换成虚拟地址
函数static inline void iounmap(void __iomem *addr)
参数*addr要取消映射的虚拟地址的首地址
参数 size_t size要映射多大的内存空间
功能释放掉 ioremap 映射的地址

注意: 物理地址只能被映射一次, 多次映射会失败。 如何查看哪些物理地址被映射过了呢? 可以使用以下命令来查看。
cat /proc/iomem


 

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木士易

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值