操作系统中的重要角色--内存管理

· 浏览次数 : 9

小编点评

本文主要讨论了内存管理在计算机系统中的重要性及实现方式。 在早期操作系统时代,程序员需要手动管理内存,包括内存布局、碎片化和安全性问题。这些问题对程序员来说是一个巨大的挑战,因为内存管理需要精确到字节级别的控制。 为了解决这些问题,虚拟内存应运而生。虚拟内存允许程序使用从0开始的一组连续虚拟地址,而不是直接访问物理内存。操作系统将内存划分为固定大小的页,与物理内存划分为相应大小的帧相对应。程序使用虚拟地址进行读写,而操作系统则负责将虚拟地址转换为物理地址。 虚拟内存的优点包括简化程序员的工作、提供连续的地址空间、解决内存有限问题以及增强安全性。然而,虚拟内存也有其缺点,如频繁的页面错误可能导致性能下降,甚至系统崩溃。 虚拟内存管理需要一种机制来存储虚拟地址和物理地址之间的映射。这种映射由页表实现,保存在每个正在运行的程序的MMU中。当程序尝试访问未映射的虚拟地址时,会发生页面错误并返回一个错误信号。 此外,分页技术是一种内存管理技巧,通过将部分页面移至硬盘驱动器来释放物理内存。当物理内存不足时,系统可以将进程交换到硬盘驱动器,从而为其他程序腾出空间。 最后,内存颠簸是指由于不断发生的页面错误而导致系统性能下降的现象。这种情况可能导致系统变得非常缓慢,甚至崩溃。 总的来说,虚拟内存为我们解决了很多问题,并简化了程序员的工作,成为目前主流的内存管理方式。

正文

在开发工作中,虽然CPU,内存和硬盘都是必不可少的硬件,不过,编程中,我们常常受到困扰的往往是内存相关的bug(编程中遇到CPU和硬盘相关的bug极少)。

这是因为我们的程序和数据虽然是存放在硬盘上的,但是运行时,CPU并不是直接从硬盘加载程序和数据的。
直接从硬盘读取指令非常慢,会成为整个系统的严重瓶颈,因此,程序及其数据首先被复制到内存(比硬盘驱动器小,但速度快得多)中,CPU从内存读取指令速度会快很多。

内存可以看作是一长串单元,每个单元都包含一些二进制数据,并标有一个称为存储器地址的数字。
内存地址的范围从0到N,取决于系统中可用的主内存量。
程序使用的地址范围称为地址空间

如下图,两个加载到内存空间中的程序Program-1Program-2
它们分别占用了内存地址0~25~8的位置。
image.png

1. 早期的内存管理

在操作系统的早期,程序可以直接访问整个主存储器,如何管理内存是程序员的工作之一。
当时编写软件的一大挑战性就在于开发人员需要设计一种管理RAM访问的好方法,并确保整个程序不会溢出可用内存。

后来,随着多任务处理的出现,当多个程序可以在同一台计算机上运行时,内存管理变得越来越棘手。
程序员不得不面对自己管理内存带来的主要问题:

  1. 内存布局问题:位于RAM中的第一个程序之后的程序将有一定量的地址空间偏移,不再是初始范围0到N(比如上面图片中的Program-2)。多个程序加载内存时,极大增加管理难度。
  2. 内存碎片问题:当程序或数据在内存中来回移动时,可用空间会被碎片化为越来越小的块。这将使它更难找到可用的空间来加载新的程序和内存中的数据
  3. 安全性问题:如果程序A不小心覆盖了程序B的内存怎么办?或者,更糟糕的是:如果它故意从另一个程序中读取敏感数据,如密码或信用卡信息,该怎么办?

因此,对于20世纪60年代早期的硬件架构师来说,急需一种自动化的内存管理形式,这样可以显著简化编程并解决更关键的内存保护问题。
最后,他们想出了今天被称为虚拟内存的东西。

2. 虚拟内存管理

虚拟内存中,程序不能直接访问物理RAM。相反,它与一个名为虚拟内存的空间交互。
操作系统与CPU一起提供这样的虚拟地址空间,并迟早将其转换为物理地址空间。

每个内存访问都是通过一个虚拟地址来执行的,该地址并不指向内存中的实际物理位置。
程序总是读取或写入虚拟地址,它完全不知道底层硬件中发生了什么。

比如,仍然是上面的Program-1Program-2,对于这两个程序来说,开发人员可以假定它们的地址都是从0开始。
而它们实际在物理内存中的位置开发人员不用关心,交给操作系统来负责就可以了。
image.png

2.1. 虚拟内存的优势

从上面的图中,我们可以看出虚拟内存的明显好处:

  1. 每个程序都有一个从0开始的虚拟地址空间,大大简化了程序员的负担,不再需要手动跟踪内存偏移
  2. 虚拟内存总是连续的,即使底层的物理内存不是连续的。操作系统完成了将可用内存块聚集到一个单一的、统一的虚拟内存块中的艰巨任务
  3. 虚拟内存机制还解决了内存有限的问题,开发时给人一种印象,不用担心物理内存还有多少(当然实际运行时,如果内存不足,操作系统会提示错误)
  4. 虚拟内存保证了安全性:操作系统会保证程序A不能读取或写入分配给程序B的虚拟内存

2.2. 虚拟内存管理的核心结构

虚拟内存机制需要一个位置来存储虚拟地址和物理地址之间的映射。
也就是说,给定虚拟地址X,系统必须能够找到对应的物理地址Y
但是,不能将这样的信息保存为1:1关系,否则就需要一个与整个物理内存一样大的虚拟地址库。

现代虚拟内存实现通过将虚拟内存物理内存解释为一长串固定大小的小块来克服这个问题(以及许多其他问题)。
虚拟内存中将这个块称为物理内存中将这个块称为

在CPU中有一个硬件组件叫做内存管理单元(MMU),它将之间的映射信息存储在一个称为页表的特殊数据结构中。
页表中每一行都包含一个索引及其对应的索引,每个正在运行的程序在MMU中都有一个自己的页表,
如下图所示:

image.png
程序Program-1占用3个内存页,编号为0~2,通过MMU页表映射到物理内存中帧3,4,8

虚拟内存的虚拟地址由两部分组成:

  1. 一个页面索引,告诉虚拟地址所属的页面
  2. 帧偏移量,表示帧内物理地址的位置

2.3. page faults是什么

当程序访问当前未映射到物理帧的虚拟地址时,会发生页面错误page faults)。
更具体地说,当页面存在于程序的页面表中,但指向物理内存中不存在或尚未可用的帧时,就会发生页面错误
比如:
image.png
MMU检测到页面错误会将消息反馈到操作系统,操作系统将尽最大努力在物理内存中找到用于映射的帧。
大多数情况下,这是一个简单的操作,除非系统内存不足。

2.4. 内存分页(paging)是什么

分页paging)是另一个内存管理技巧:操作系统将一些页面移动到硬盘驱动器,以便在没有更多物理内存可用时为其他程序或数据腾出空间。
分页有时也被称为交换swapping),交换是将整个进程移动到磁盘上。

分页给程序一种无限可用内存的错觉,操作系统乐观地允许虚拟内存地址空间大于物理内存地址空间,知道数据可以在需要时移入和移出硬盘驱动器。
有些系统(如Windows)使用一个特殊的文件,称为分页文件。其他操作系统(例如Linux)有一个称为交换区域的专用硬盘分区。

不过,需要注意的是,硬盘驱动器比主内存慢得多。
因此,当发生页面错误并且页面临时移动到硬盘驱动器时,操作系统必须从缓慢的介质中读取数据并将其移回内存,从而导致延迟。
总而言之,更少的分页意味着系统可以更有效地运行。

2.5. 内存颠簸(Thrashing)是什么

当系统在分页上花费的时间多于运行应用程序的时间时,就会发生抖动,这是由不断的页面错误流触发的。
这是一种极端的情况,比如你运行了太多的程序,占用了整个内存以及在硬盘上的分页区域,
这时就容易发生页面错误,操作系统为了跟上大量的页面错误请求,不断地在硬盘驱动器和物理内存之间移动数据,使系统陷入停顿。

解决这个问题可以通过增加内存的容量,或者减少正在运行的程序的数量,或再次通过调整交换文件的大小来避免抖动。

2.6. 存储保护

虚拟内存还提供了跨运行应用程序的安全性,比如你的浏览器无法窥视你的文本编辑器的虚拟内存,反之亦然。
内存保护的主要目的是防止进程访问不属于它的内存。

内存保护机制通常由MMU及其管理的页表提供。当一个程序试图访问一部分它不拥有的虚拟内存时,就会触发一个无效的页面错误。
MMU和操作系统捕获信号并引发故障条件,称为分段错误(就是耳熟能详的segmentation fault),操作系统通常会终止程序作为响应。

3. 总结

总之,虚拟内存为我们解决了很多问题,也简化了简化了程序员的工作,是目前主流的内存管理方式。

与操作系统中的重要角色--内存管理相似的内容:

操作系统中的重要角色--内存管理

在开发工作中,虽然CPU,内存和硬盘都是必不可少的硬件,不过,编程中,我们常常受到困扰的往往是内存相关的bug(编程中遇到CPU和硬盘相关的bug极少)。 这是因为我们的程序和数据虽然是存放在硬盘上的,但是运行时,CPU并不是直接从硬盘加载程序和数据的。直接从硬盘读取指令非常慢,会成为整个系统的严重

零拷贝并非万能解决方案:重新定义数据传输的效率极限

本文讨论了零拷贝在优化数据传输效率方面的局限性。尽管零拷贝技术在减少数据传输过程中的内存拷贝次数方面有很大的优势,但它并非适用于所有情况。文章介绍了一些其他的优化方法,如异步I/O和直接I/O的组合、根据文件大小选择不同的优化方式。至此,我们的计算机基础专栏就结束了,不知道大家有没有发现,操作系统底层提供了丰富的解决方案来支持应用程序的复杂性和可扩展性。对于任何工作中遇到的问题,我们都可以从操作系统的角度寻找解决方法。

进程调度的原理和算法探析

本文探讨了进程调度的原理和算法,并提供了全面的概述。进程调度是操作系统中的重要组成部分,用于决定进程的执行顺序和分配CPU时间。我们讨论了优先级调度和时间片轮转调度算法。优先级调度根据进程的优先级确定执行顺序,可以分为抢占式和非抢占式。时间片轮转调度将CPU时间划分为固定大小的时间片,每个进程在一个时间片内执行。合理设置时间片长度能够避免资源浪费和频繁的上下文切换。最短作业优先和最短剩余时间优先是

如何用windows任务视图管理多个程序,提高.net开发效率

在 Windows 操作系统中,任务栏是一个非常重要的工具栏,用来显示当前正在运行的程序和任务。如果同时运行了很多程序,任务栏上的图标就会变得非常拥挤,不方便管理和切换。为了提高工作效率,可以通过任务视图来将这些运行程序分组,以便更好地管理和切换。 任务视图是 Windows 操作系统中的一个功能,

1.13 导出表劫持ShellCode加载

在`Windows`操作系统中,动态链接库`DLL`是一种可重用的代码库,它允许多个程序共享同一份代码,从而节省系统资源。在程序运行时,如果需要使用某个库中的函数或变量,就会通过链接库来实现。而在`Windows`系统中,两个最基础的链接库就是`Ntdll.dll`和`Kernel32.dll`。Ntdll.dll是Windows系统内核提供的一个非常重要的动态链接库,包含了大量的系统核心函数,如

科大讯飞:说说零拷贝技术和多路复用技术?

零拷贝技术和多路复用技术是现代计算机系统和网络编程中两项重要的优化手段,旨在提高数据处理和传输的效率。如高性能框架 Netty 中,即使用了零拷贝技术又使用了多路复用技术,同时来保证 Netty 框架的高性能运行。 1.零拷贝技术 零拷贝(Zero-copy)技术是一种计算机操作系统中用于提高数据传

操作系统中文件系统的实现和分配方式探析(上)

本文主要讨论了操作系统中文件系统的实现和分配方式。首先介绍了虚拟文件系统(VFS)作为中间层,统一了不同文件系统的接口。然后介绍了文件的物理结构,包括文件块和逻辑块之间的映射关系。接着详细讨论了连续分配方式的特点和优缺点,包括顺序访问和随机访问的效率,以及磁盘空间碎片和文件长度扩展不方便的问题。最后提到了非连续分配方式来解决连续分配方式的问题,并留下了下次讨论的悬念。文件系统的实现和分配方式对于操作系统的性能和可靠性都有重要影响,因此深入理解和研究文件系统的原理和机制是非常有价值的。

2.4 PE结构:节表详细解析

节表(Section Table)是Windows PE/COFF格式的可执行文件中一个非常重要的数据结构,它记录了各个代码段、数据段、资源段、重定向表等在文件中的位置和大小信息,是操作系统加载文件时根据节表来进行各个段的映射和初始化的重要依据。节表中的每个记录则被称为`IMAGE_SECTION_HEADER`,它记录了一个段的各种属性信息和在文件中的位置和大小等信息,一个文件可以由多个`IMA

GO 协程

转载请注明出处: 线程是进程中的一个实体,被系统独立调度和分派的基本单位。线程自己不拥有系统资源,只拥有运行中必不可少的资源。同一进程中的多个线程并发执行,这些线程共享进程所拥有的资源。 协程是一种比线程更加轻量级的存在,重要的是,协程不被操作系统内核管理,协程完全是由程序控制的,不需要手动创建和管

[转帖]Linux中find命令使用示例

https://zhuanlan.zhihu.com/p/99170116 Linux查找命令是类Unix操作系统中最重要且最常用的命令行实用程序之一。 查找命令可以根据你设定的参数匹配的文件指定的条件来搜索和查找文件或目录的列表。 查找可以在多种条件下使用,例如可以按权限,用户,组,文件类型,日期