首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Linux内核中,virt_to_phys和CPU的MMU之间有什么关系?

在Linux内核中,virt_to_phys和CPU的MMU之间有什么关系?
EN

Stack Overflow用户
提问于 2015-04-17 09:23:40
回答 6查看 6K关注 0票数 15

我正在阅读关于Linux内存管理的文章。我知道

Linux内核负责创建和维护页表,但使用CPU的内存管理单元(MMU)将进程的虚拟内存访问转换为相应的物理内存访问。

但是,我也知道内核可以使用它的一些函数来管理内存,如virt_to_phys()virt_to_page()__pa()、.

示例:

代码语言:javascript
运行
复制
static inline unsigned long virt_to_phys(volatile void *address)
{
    return __pa(address);
}

用于将虚拟地址转换为物理地址。

我对他们很困惑。请告诉我MMU的翻译和内核的翻译之间的关系,并区分它们。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2015-04-17 20:45:53

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

但是,当CPU执行访问内存的指令时,CPU执行从进程虚拟地址到物理地址的转换,物理地址指示内存中的实际位置。

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

代码语言:javascript
运行
复制
/**
 *  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,定义为:

代码语言:javascript
运行
复制
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将它们操作的虚拟地址转换为数据实际上位于内存中的物理地址。

票数 10
EN

Stack Overflow用户

发布于 2015-04-18 14:19:44

MMU地址转换是一种硬件(Cpu)行为。转换必须完成,因为物理地址是硬件可以用来访问内存的有效地址。另一方面,内核函数(如va_to_pa() )被用来将内核逻辑地址( va )转换为物理地址( pa ),这意味着内核使用物理地址以外的虚拟地址,尽管它只是va和pa之间的常数移位。

内核指令和数据都在一个虚拟地址中,但是内核使用物理地址来做很多事情,比如准备页面表条目,为设备获取dma地址等等。所以内核需要像va_to_pa()这样的函数。

票数 2
EN

Stack Overflow用户

发布于 2015-04-17 10:49:18

根据我的理解,内核端的任何物理地址的使用都只是为了参考,并且很可能只是为了任何实际的更改/移动而被转换回来。这有很多原因,其中一个原因是内存可能被重新分配给另一个用途,IE将数据从物理内存移动到页文件(磁盘上内存),或者在物理内存分配中移动,如果需要更多的数据空间。因此,如果内核只是在不告诉您的情况下移动它,那么使用物理地址就不太好了。这里有一个关于这个问题的有趣的地方。 还有更多的细节。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29695247

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档