操作系统如何阻止程序访问内存?

我目前的理解是

  • 我可以用C编写操作系统

  • 我可以用C编写该操作系统的程序

  • 编写操作系统时,我可以看到所有内存

  • 当我编写程序时,操作系统会向其他程序隐藏内存。

  • 每当程序在操作系统中运行时,该程序就好像该程序分配的内存是计算机拥有的所有内存一样

CPU / OS如何实现此目的?这是纯粹在软件级别实现的吗?还是也需要硬件实现?

aqmes 回答:操作系统如何阻止程序访问内存?

它不完全在软件级别上。用几句话来介绍英特尔架构:

每个进程的地址空间是隔离的;每个进程具有相同的虚拟地址空间(简化为:0x00000000到0xffffffff),它们映射到不同的物理位置。

地址空间代表内存页面的集合。仅在需要时才对页面进行物理映射。从物理内存中删除长时间未访问的页面(有特殊算法);如果它们包含动态修改的内容,它们将存储在硬盘驱动器上的“交换”文件中。

每个页面都属于特定进程(某些系统页面除外),已分配虚拟地址和访问标志:读/写/执行。似乎是连续数组的东西,可以分配在几个不连续的页面上,并且其中一些甚至可以现在换出到硬盘上。

程序(进程)只能看到其自己的地址空间。有几种方法可以到达其他进程的空间,但是常规程序很少这样做。

不能完全访问地址空间:如果程序尝试访问未分配的地址或写入受写保护的页面,则会触发内存冲突。

通常,程序只能在其自己的地址空间中分配,取消分配或更改页面的访问标志。内存有多种类型(用于加载可执行映像,用于堆栈以及几种不同类型的可分配内存)。

对不起,我不记得那本书的书名,很久以前就读过。

,
  

操作系统如何阻止程序访问内存?

简短的回答:在x86处理器上,他们通过激活Protected Mode(32-bit)Long Mode(64-bit)来做到这一点。 ARM或其他处理器实现类似的概念。 保护模式保护彼此不同的进程的内存空间-为每个进程提供自己的内存空间。这个概念称为Virtual Memory

在硬件中,这是通过MMU(用于内存)或IOMMU(用于IO内存)来实现的,它们阻止了对内存空间某些区域的访问。

  

CPU / OS如何实现此目的?这是纯粹在软件级别实现的吗?还是也需要硬件实现?

如上所述,最好在硬件中高效实现。不能完全在软件级别上(有效地)完成此操作。

作为针对高级读者的思想实验:
尝试在Real Mode中实现进程隔离(防止另一个进程访问该进程的内存)。

一个(合理的)答案:
我知道的软件实现的唯一方法是 Virtual Machine 的方法,该方法检查内存访问的所有边界(所有指令)-本质上是MMU所做的。

,

当前常见的解决方案是使用MMU(内存管理单元)。无需只考虑intel或arm。

尽管术语“虚拟内存”的使用存在问题,您仍可以查找术语“虚拟内存”和“物理内存”。

物理内存是处理器的地址空间,范围从0x000 ... 0000到0xFFF ... FFF,但是地址的位很多。

虚拟内存不需要单独的处理器模式,但是在一般的实现中需要,并且可以隔离内核(如果需要的话,可以使用OS)和应用程序之间。在处理器和mmu之间的核心地址总线上,提供了id以及​​地址和数据。操作系统设置mmu表,这些表定义了虚拟内存的块并描述了物理地址。因此,特定应用程序在0x00000000处的16K字节虚拟地址块可能会映射到物理内存中的0x12300000。对于同一应用程序,0x00004000可能会映射到0x32100000,依此类推,这使操作系统的内存分配更加容易,如果您想分配一个内存,则不必查找线性/对齐的空闲内存块,但可以构建它较小的未分配/可用内存块中。除其他外,这使应用程序可以认为它可以访问处理器的很大一部分存储空间。

有不同的设计实现,但是为了保护操作系统和应用程序,总线上使用的ID区分了应用程序和操作系统。如果总线事务包含一个id和一个id不能访问的地址的组合(每个块都有访问/保护位,以某种形式指示一个id是否可以访问该虚拟地址),则mmu会产生故障,是处理器特定的某种异常/中断,以处理器特定的方式将处理器切换到保护/内核模式并命中中断/异常处理程序。这不一定是一件坏事。例如,当运行虚拟机而不是应用程序时,可以有意地设计虚拟机软件,以使特定的虚拟地址是某些外围设备(例如以太网控制器)的仿真,以便vm可以访问网络。当应用程序命中该地址时,便会发生故障,而不是关闭应用程序并通知用户有问题,而是基于该地址,通过对应用程序做出反应或将结果返回给应用程序来模拟外围设备从真实的外围设备告诉。错误的另一个特征是虚拟内存的外行(不是程序员/软件/硬件工程师)版本。这就是您的应用程序可能认为它可以访问所有计算机内存的地方。应用程序可能已用完系统中的所有空闲内存(RAM)。但是在它们的虚拟地址空间中,它们实际上都没有做到这一点,有一次应用程序可能已经将物理0x11100000分配给了虚拟0x20000000,但是系统上需要分配内存,并且没有更多可用空间了。操作系统可以使用一种算法来确定该应用程序已经一段时间没有使用其空间,或者更可能是随机彩票,并以0x11100000的物理空间获取了该块并将其内容复制到硬盘/(非ram存储)中,标记为虚拟0x20000000,以便在访问时会出错,并为当前的内存分配请求提供物理0x11100000(可以是同一应用程序,也可以是其他应用程序)。当此应用程序出现并以0x20000000访问内存块时,操作系统出现故障,选择了其他内存块,将其保存到磁盘,将其标记为故障,并从该应用程序处取出0x20000000从磁盘放置它在ram中,释放故障,应用程序继续运行。这就是为什么当您的系统内存不足而性能下降到有时会称为虚拟内存的“交换”内存中时的原因。

如果存在mmu,并且处理器设计为与操作系统一起使用,那么理想情况下,可以使用一种快速的方法来切换mmu表。为了使单线程处理器简化这一过程,即使用户感觉到发生了很多事情,一次也只能运行一件事,一次只能运行一组指令,它们要么来自特定的应用程序,要么来自特定的应用程序。操作系统中的处理程序。每个处理器ID都需要每个应用程序和内核本身的mmu表(通常不关闭mmu,而只是简单地让内核完全访问内存空间,或者mmu知道未检查特定的ID,这取决于mmu的设计/系统)。 mmu表存在于内存中,但是mmu不必经过自身就可以达到它的目的,操作系统根本不会将该内存分配给任何人,而是对其进行保护。 mmu可以是这样的,它可以将虚拟地址的id和上半部分组合起来以找到mmu表条目,或者在一个单线程系统中,可以有一个活动表,并且os切换使用哪个表或哪个id可以访问块,或者以这种方式考虑一下,单个线程系统可能只有两个id。在这里变得太模糊了,您需要查看特定的处理器/体系结构/实现,以了解该处理器如何工作,处理器模式如何工作,mmu是如何生成的id等等,以此类推。

这里的另一个功能使我们所有人的生活变得更加轻松,这是因为它还允许应用程序A在0x00000000处拥有其程序,而应用程序B在(虚拟地址)0x00000000处拥有其程序,而应用程序C在0x00000000年拥有其程序,因为他们的物理地址都在不同的地方。但是我们现在可以为该操作系统编译程序,以便它们在相同的内存空间中运行。预先安装或不使用mmu,然后进行以下操作:1)您可能没有受到保护,但是2)您肯定仍然可以使用带有应用程序的操作系统。您将需要操作系统来移动内存或强制执行位置无关的代码,以便在启动时,每个应用程序要么从一个已知地址启动,但是操作系统已移开/交换了另一个应用程序,或者它们与位置无关,并且每个应用程序都在一个位置启动。不同的空间。为了支持内存分配,操作系统将需要更加努力地保持跟踪,并尝试拥有一种试图避免碎片化的算法,有时在应用程序重新分配时必须复制数据。

本文链接:https://www.f2er.com/3088010.html

大家都在问