【问题标题】:How MMU(Memory management Unit) unit in a processor protects the memory segments处理器中的 MMU(内存管理单元)单元如何保护内存段
【发布时间】:2010-09-30 06:41:24
【问题描述】:

在介绍一种嵌入式处理器架构时,我看到了块 MMU,它主要提到了内存保护功能。

我想知道,

MMU 如何提供这种保护以及为什么需要它? 内存保护是什么意思?

除了保护之外,MMU 还有什么其他用途(如虚拟寻址)?

请考虑一个没有操作系统的嵌入式系统。

__卡努

【问题讨论】:

    标签: architecture embedded


    【解决方案1】:

    对于使用内存的处理器(大多数),有某种内存接口,有些有名称(如 amba、axi、wishbone),有些没有。从处理器的角度来看,这是地址和数据,请读取或写入该地址处的内容。在过去的美好时光中,您将拥有一条总线,并且您的闪存、内存和外围设备将坐在该总线上,查看地址的某些(通常是高位)位以确定它们是否被寻址,如果是,则读取或跳转否则数据总线保持三态。今天,取决于芯片等,一些内存解码发生在内核中或内核附近,您与内核或芯片的公共接口可能有多个总线,可能有特定的闪存总线,特定的 sram 总线和特定的 DRAM公交车等

    所以第一个问题是平坦的线性地址空间,即使分为闪存和内存,内存部分也是平坦的,地址 0 到 N-1 为 N 个字节。对于非嵌入式操作系统,如果只有某种方式让程序假设它们都从地址 0 或地址 0x100 或地址 0x8000 开始,而不是必须以某种方式编译下一个可用内存,那么为了让人们的生活更轻松空间是,或者操作系统不必在任务切换时将程序完全移出较低的内存并用另一个程序替换它。一个古老的简单方法是使用 intels segment:offset 方案。程序总是在同一个地方开始,因为在启动程序之前调整了代码段,并且使用偏移量执行(这个模型的非常简化的视图),当程序之间的任务切换时你只需更改代码段,恢复 pc 为下一个节目。一个程序可能位于地址 0x1100,而另一个程序位于地址 0x8100,但两个程序都认为它们位于地址 0x0100。对所有开发人员来说都很容易。 MMU 通过在处理器总线上获取该地址并将其称为虚拟地址来提供相同的功能,mmu 通常位于处理器内存接口和芯片/世界其他部分之间的处理器附近。因此,您可以再次让 mmu 看到地址 0x0100 在表中查找并转到物理地址 0x0100,然后当您切换任务时更改表,以便下一次获取 0x0100 到 0x1100。每个程序都认为它在地址 0x0100 处运行,链接、编译、开发、加载和执行代码的痛苦更少。

    下一个特性是缓存、内存保护等。因此处理器及其内存控制器可能会在到达 mmu 之前解码一些地址,可能是某些核心寄存器,也可能是 mmu 控制自己。但是内存和外围设备之类的其他东西可能会在 mmu 的另一侧进行寻址,在缓存的另一侧,通常是 mmu 之外的下一层洋葱。例如,当轮询串行端口以查看是否有另一个字节可用时,您不希望缓存数据访问,这样串行端口状态寄存器的第一次读取实际上会在物理总线上输出并触及串行端口,然后全部随后的读取读取缓存中的陈旧版本。您确实希望将其用于 ram 值,即缓存的目的,但是对于状态寄存器之类的易失性事物,这是非常糟糕的。因此,根据您的系统,在启用 mmu 之前,您可能无法打开数据缓存。例如,ARM 上的内存接口具有指示访问类型的控制位,它是不可缓存的访问,还是可缓存的,突发的一部分,诸如此类。因此,您可以启用独立于数据缓存的指令缓存,并且在没有 mmu 的情况下,它将这些控制信号直接传递到缓存控制器,然后连接到外部世界(如果它没有处理事务)。因此,您的指令获取可以缓存其他所有未缓存的内容。但是要缓存数据 ram 访问而不是来自串行端口的状态寄存器,您需要做的是为 mmu 设置表,在您的嵌入式环境中,您可以选择简单地一对一映射 ram,这意味着地址 0x1000 虚拟变为 0x1000 物理,但您现在可以为该内存块启用数据缓存位。然后对于您的串行端口,您可以将虚拟地址映射到物理地址,但您清除该内存空间块的数据缓存启用位。现在您可以启用数据缓存,内存读取现在被缓存(因为它们通过 mmu 时的控制信号被标记为这样,但是对于您的寄存器访问,控制信号指示不可缓存)。

    您当然不必将虚拟与物理一对一映射,这取决于嵌入式或非嵌入式、操作系统与否等。但这就是您的保护所在。在操作系统中最容易看到。不应允许应用程序层的应用程序访问受保护的系统内存、内核等。不应破坏其他应用程序的内存空间。所以当应用程序启动时,mmu 表反映了它允许访问哪些内存以及不允许访问哪些内存。程序不允许的任何地址都被 mmu 捕获,产生异常/故障(中断),内核/主管获得控制并可以处理该程序。您可能还记得早期 Windows 时代的“一般保护故障”一词,在公司的营销和其他利益集团决定我们应该更改名称之前,它直接来自英特尔手册,当您出现故障时会触发中断不属于其他类别,例如关于测试 A bob、B ted、C alice、D 的多项选择题,以上都不是。一般保护错误不是上述类别,但受到的影响最大,因为这是您的程序尝试访问分配的内存空间之外的内存或 i/o 时遇到的问题。

    mmus 的另一个好处是 malloc。在 mmus 之前,内存分配必须使用方案来重新安排内存以将大的空块保留在中间。对于下一个大 malloc,尽量减少“使用 4meg free 为什么我的 1kbyte alloc 失败?”。现在,就像磁盘一样,您将内存空间分成这些 4kbyte 或一些类似大小的块。大小为一个块或更小的 malloc,获取内存中的任何空闲块,使用 mmu 表条目指向它,并为调用者提供与该 mmu 条目相关的虚拟地址。你想要 4096*10 字节,诀窍是不必找到那么多线性内存,而是找到 10 个线性 mmu 表条目,取任意 10 个内存块(不一定相邻)并将它们的物理地址放在 10 个 mmu 条目中。

    底线,“如何”它通常位于处理器和缓存之间,或者如果没有缓存,则位于物理内存总线之间。 mmu 逻辑查看地址,使用该地址查看表格。表中的位包括物理地址加上一些控制信号,其中包括可缓存的,加上一些指示这是有效条目还是受保护区域的方式。如果该地址受到保护,则 mmu 会向内核触发中断/事件。如果有效,它会将虚拟地址修改为 mmu 另一端/外部的物理地址,并且可缓存位之类的位用于告诉 mmu 另一端的任何内容这是什么类型的事务,指令,数据,可缓存、突发等。对于嵌入式、非操作系统、单任务系统,您可能只需要一个 mmu 表。例如,在操作系统中执行保护的一种快速方法是为每个应用程序创建一个表或表的一个子集(该树类似于目录结构),这样当您切换任务时,您只需更改一件事,表的开始或树的一个分支的开始,以将虚拟地址更改为物理地址并为树的该分支分配内存(保护)。

    【讨论】:

    • 这对 MMU 概念的理解非常正确。谢谢!
    • 补充一下关于 malloc 的想法,因为您在一个虚拟地址空间中,它可能比您拥有的物理内存量大得多,您更有机会找到线性 mmu 表条目。在堆中可能有 100*4096 字节的内存可以直接通过物理访问进行管理,而现在您在同一系统中只有 100 个 mmu 表条目,您可能有数百个 mmu 表条目可用于管理这 100 个物理内存块。
    【解决方案2】:

    MMU(内存管理单元)是系统的基本块,它们希望拥有独立且受保护的内存空间。我将保持简单,因为可以编写有关内存管理硬件和策略的整本书...

    如果没有保护,在任何进程中运行的程序都可以访问任何其他进程的内存。即使您忽略了安全隐患,这也意味着一个程序中的错误可能会覆盖属于某个其他进程的内存。调试这类问题并不容易,因为症状与原因相去甚远。

    因此,需要某种组织原则,以便每个进程只能看到和修改分配给它的内存。而且,由于会发生错误,因此该组织必须得到硬件的支持,这样即使意外访问错误的内存部分也很困难。

    这样做的一个好处是还可以使每个进程的内存映射看起来相同。链接器可以将每个程序定位在相同的起始地址,将堆栈和堆放在可预测的区域,并为与内核交互保留内存。

    MMU 是实现从进程使用的逻辑地址到硬件使用的物理地址的转换的硬件组件。它还提供安全功能,例如仅将内存的某些部分标记为可执行文件。它提供了内核实现进程交换和虚拟内存所需的数据结构,使得属于进程A的内存页面甚至不能被进程B看到,但A和B都可以被可信内核看到。

    为了以实际的方式实现这一点,物理内存被划分为页面,通常大小为 4KB。每个逻辑地址被分解成一个页码和一个偏移量。页码索引 MMU 中的一个表,该表将每个逻辑页转换为某个物理地址。这种转换发生在每个内存访问周期。单个物理页面可以映射到任何进程(在这种情况下,它可能也在空闲页面池中),可以映射到一个或多个。

    进程的堆栈、数据和堆通常由映射到该进程的页面组成。这有助于防止一个进程中的错误影响其他进程,因为每个进程只能写入自己的堆栈、数据和堆页面。

    如果同一页物理内存映射到多个进程,则这些进程可见。这就是共享 Windows 上的 DLL 或 Unix 上的 .so 的方式:保存其程序文本的页面被映射到与其链接的每个进程。

    MMU 有一种机制,当访问尚未映射到进程的页面时会引发异常。处理该异常可以实现虚拟内存,并随着进程需求的变化增加分配给进程的内存量。

    【讨论】:

    • 好的。那么没有操作系统来支持 MMU 的系统呢?这意味着在没有操作系统的嵌入式系统中如何定义 MMU?
    • @Renjith G:如果没有操作系统,您通常会将 MMU 配置到单个地址空间中,通常使用直接物理 = 虚拟映射。您可能会将代码空间配置为只读,以保护其免受意外或恶意修改。然而,没有操作系统或 RTOS 意味着单线程/进程操作,因此保护一个线程或进程数据空间不受另一个线程或进程数据空间影响的能力不是问题。
    • 它提供了内核实现进程交换和虚拟内存所需的数据结构 内核如何知道该结构?
    • 进程的堆栈、数据和堆通常由映射到该进程的页面组成。谁映射它们,MMU ?
    【解决方案3】:

    内存保护意味着系统上的每个进程都运行在它自己的虚拟地址空间中,本质上,每个进程运行起来就好像它拥有一个系统的主内存一样。这也意味着一个进程不能更改为另一个进程保留的内存。这对于系统稳定性和安全性至关重要(例如,程序不能简单地扫描系统内存来定位您刚刚输入的密码)。

    MMU 提供了很多很多其他功能(虚拟内存、动态重定位等)。

    这就是为什么。要回答“如何”,您应该做一些进一步的reading

    【讨论】:

      猜你喜欢
      • 2023-03-15
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-28
      • 1970-01-01
      相关资源
      最近更新 更多