一个系统中的进程是与其他进程共享 CPU 和主存资源的。然而,共享主存会形成一些特殊的挑战。
虚拟内存提供了三个重要的能力:
LWN.net 上有一系列的 “What every programmer should know about memory” 文章你需要读一下。当然,你可以直接访问一个完整的 PDF 文档。下面是这个系列文章的网页版列表。读完这个列表的内容,你基本上就对内存有了一个比较好的知识体系了。
分类:
缺点:
优点:
缺点:
段是信息的逻辑单位。
分段的目的是更好地满足用户需求。
一个段通常包含着一组属于一个逻辑模块的信息,更容易实现信息的共享和保护。
分段对用户是可见的,用户编程时需要显式给出段名。
段的大小不固定,取决于用户编写的程序(低级语言)。
段表:段号、段长、基址
页是信息的物理单位。分页的目的是为了实现离散分配,提高内存利用率。
分页仅仅是系统管理上的需要,完全是系统行为,对用户不可见。
作用:记录进程中各个页与所占用内存块的关系,形成映射。
单页表遇到的问题:
实现对页表本身的虚拟存储。
注意:
进程分段 =》段分页 =》内存分块
维护一个段表和若干个页表
程序不需全部装入即可运行,运行时根据需要动态调入数据,若内存不够,还需换出一些数据。
访问的信息不在内存时,由操作系统负责将所需信息从外存调入内存
页表结构:内存块号 中断位P 访问位A 修改位M 外存地址
缺页中断与一般的 I/O 中断区别:
内存空间不够时,将内存中暂时用不到的信息换出到外存,换出时注意清掉快表中的缓存。
理想置换算法要求:被换出的页面在以后的运行中不需要。
计算机系统的主存被组织成一个由 M 个连续的字节大小的单元组成的数组。每个字节都有一个唯一的物理地址。
在物理地址与虚拟地址间加个地址翻译就构成了虚拟寻址。
地址空间是一个非负整数地址的有序集合。
地址空间的概念是很重要的,因为它清楚地区分了数据对象(字节)和他们的属性(地址)。
内存成了对硬盘的缓存,虚拟页面可划分为未分配的、未缓存的和已缓存的。
逻辑地址到物理地址
回到本章前言,“虚拟内存是强大的”。
将一个文件或其他对象映射到进程的地址空间,实现文件磁盘地址和进程地址空间中一段虚拟地址的一一对应。
实现了这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用 read、write 等系统调用函数。
相反,内核空间对这段区域的修改也直接反应用户空间,从而可以实现不同进程的文件共享。
简单总结,有如下特点:
为什么要动态分配内存?因为很多时候只有在运行时才知道某些数据结构的大小。
malloc 与 mmap、munmap 区别是什么?
这一部分可以借鉴操作系统为进程分配内存的操作。
一个进程终止后,其占用的内存由操作系统来释放和重新分配。
进程存活时,释放掉不用的内存就得交给程序本身了,C / C++ 把这活交给了程序员,Java 这类的有自己的垃圾回收器。