上一节: 操作系统 - 多线程
上一节
下一节: 操作系统 - 虚拟内存
下一节
操作系统 - 内存管理
简述
内存管理是操作系统的功能,它处理或管理主内存并在执行期间在主内存和磁盘之间来回移动进程。内存管理跟踪每个内存位置,无论它是分配给某个进程还是空闲的。它检查要分配给进程的内存量。它决定了哪个进程在什么时候获得内存。每当某些内存被释放或未分配时,它都会跟踪,并相应地更新状态。
本教程将教您与内存管理相关的基本概念。
进程地址空间
进程地址空间是进程在其代码中引用的一组逻辑地址。例如,当使用 32 位寻址时,地址范围可以从 0 到 0x7fffffff;也就是说,2^31 个可能的数字,总理论大小为 2 GB。
操作系统在为程序分配内存时负责将逻辑地址映射到物理地址。在分配内存之前和之后,程序中使用了三种类型的地址 -
序列号
内存地址和描述
1
Symbolic addresses 符号地址
源代码中使用的地址。变量名、常量和指令标签是符号地址空间的基本元素。
2
Relative addresses 相对地址
在编译时,编译器将符号地址转换为相对地址。
3
Physical addresses 物理地址
加载程序在程序加载到主存储器时生成这些地址。
虚拟地址和物理地址在编译时和加载时地址绑定方案中是相同的。虚拟地址和物理地址在执行时地址绑定方案中有所不同。
程序生成的所有逻辑地址的集合称为logical address space. 与这些逻辑地址对应的所有物理地址的集合称为physical address space.
从虚拟地址到物理地址的运行时映射由作为硬件设备的内存管理单元 (MMU) 完成。MMU 使用以下机制将虚拟地址转换为物理地址。
基址寄存器中的值被添加到用户进程生成的每个地址,在发送到内存时被视为偏移量。例如,如果基址寄存器值为 10000,则用户尝试使用地址位置 100 将被动态重新分配到位置 10100。
用户程序处理虚拟地址;它永远不会看到真实的物理地址。
静态与动态加载
在开发计算机程序时选择静态或动态加载。如果您必须静态加载程序,那么在编译时,将编译和链接完整的程序,而不会留下任何外部程序或模块依赖。链接器将目标程序与其他必要的目标模块组合成一个绝对程序,其中还包括逻辑地址。
如果您正在编写动态加载的程序,那么您的编译器将编译该程序,并且对于您想要动态包含的所有模块,将仅提供引用,其余工作将在执行时完成。
在加载时,与static loading,绝对程序(和数据)被加载到内存中以便开始执行。
如果您正在使用dynamic loading,库的动态例程以可重定位的形式存储在磁盘上,并且仅在程序需要时才加载到内存中。
静态与动态链接
如上所述,当使用静态链接时,链接器将程序所需的所有其他模块组合成单个可执行程序,以避免任何运行时依赖。
使用动态链接时,不需要将实际的模块或库与程序链接,而是在编译和链接时提供对动态模块的引用。Windows 中的动态链接库 (DLL) 和 Unix 中的共享对象是动态库的好例子。
交换
交换是一种机制,其中一个进程可以暂时从主内存(或移动)交换到辅助存储(磁盘),并使该内存可供其他进程使用。在稍后的某个时间,系统将进程从辅助存储器交换回主存储器。
虽然性能通常会受到交换进程的影响,但它有助于并行运行多个大型进程,这就是原因Swapping is also known as a technique for memory compaction.
交换进程所花费的总时间包括将整个进程移动到辅助磁盘然后将进程复制回内存所花费的时间,以及进程重新获得主内存所花费的时间。
让我们假设用户进程的大小为 2048KB,并且在将进行交换的标准硬盘上,数据传输速率约为每秒 1 MB。1000K 进程进出内存的实际传输将花费
2048KB / 1024KB per second
= 2 seconds
= 2000 milliseconds
现在考虑进出时间,它将花费完整的 4000 毫秒加上进程竞争重新获得主内存的其他开销。
内存分配
主存储器通常有两个分区 -
Low Memory− 操作系统驻留在此内存中。
High Memory− 用户进程保存在高内存中。
操作系统使用以下内存分配机制。
序列号
内存分配和描述
1
Single-partition allocation
在这种类型的分配中,重定位寄存器方案用于保护用户进程相互之间以及操作系统代码和数据的更改。重定位寄存器包含最小物理地址的值,而限制寄存器包含逻辑地址范围。每个逻辑地址必须小于限制寄存器。
2
Multiple-partition allocation
在这种类型的分配中,主内存被分成许多固定大小的分区,每个分区应该只包含一个进程。当一个分区空闲时,从输入队列中选择一个进程并加载到空闲分区中。当进程终止时,该分区可用于另一个进程。
碎片化
随着进程被加载和从内存中删除,可用内存空间被分成小块。有时会发生这种情况,因为考虑到它们的小尺寸并且内存块仍未使用,因此无法将进程分配给内存块。这个问题被称为碎片。
碎片有两种类型 -
序列号
碎片化和描述
1
External fragmentation
总内存空间足以满足一个请求或在其中驻留一个进程,但它不是连续的,因此不能使用。
2
Internal fragmentation
分配给进程的内存块更大。内存的某些部分未被使用,因为它不能被另一个进程使用。
下图显示了碎片如何导致内存浪费,并且可以使用压缩技术从碎片内存中创建更多空闲内存 -
可以通过压缩或混洗内存内容以将所有空闲内存放在一个大块中来减少外部碎片。为了使压缩可行,重定位应该是动态的。
可以通过有效分配最小但足够大的分区来减少内部碎片。
寻呼
计算机可以寻址比系统上实际安装的数量更多的内存。这个额外的内存实际上被称为虚拟内存,它是硬件的一部分,用于模拟计算机的 RAM。分页技术在实现虚拟内存中起着重要作用。
分页是一种内存管理技术,其中进程地址空间被分成相同大小的块,称为pages(大小是 2 的幂,介于 512 字节和 8192 字节之间)。进程的大小以页数来衡量。
类似地,主内存被划分为小的固定大小的(物理)内存块,称为frames帧的大小与页的大小保持一致,以优化主存的利用率,避免外部碎片。
地址翻译
页面地址被调用logical address并由page number和offset.
Logical Address = Page number + page offset
帧地址被调用physical address并由 a 表示frame number和offset.
Physical Address = Frame number + page offset
一种数据结构称为page map table用于跟踪进程的页面与物理内存中的帧之间的关系。
当系统将帧分配给任何页面时,它会将这个逻辑地址转换为物理地址,并在页表中创建条目以在整个程序执行过程中使用。
当一个进程要被执行时,它的相应页面被加载到任何可用的内存帧中。假设您有一个 8Kb 的程序,但您的内存在给定时间点只能容纳 5Kb,那么分页概念就会出现。当计算机的 RAM 用完时,操作系统 (OS) 会将空闲或不需要的内存页面移动到辅助内存中,以便为其他进程释放 RAM,并在程序需要时将它们带回来。
该过程在程序的整个执行过程中继续进行,其中操作系统不断从主存储器中删除空闲页面并将它们写入辅助存储器并在程序需要时将它们带回。
分页的优缺点
以下是分页的优缺点列表 -
分页减少了外部碎片,但仍然受到内部碎片的影响。
分页很容易实现,并被认为是一种有效的内存管理技术。
由于页面和框架的大小相同,交换变得非常容易。
页表需要额外的内存空间,因此可能不适合具有小 RAM 的系统。
分割
分段是一种内存管理技术,其中每个作业被分成几个不同大小的段,每个模块包含执行相关功能的片段。每个段实际上是程序的不同逻辑地址空间。
当要执行一个进程时,尽管每个段都被加载到一个连续的可用内存块中,但它的相应分段被加载到非连续内存中。
分段内存管理的工作方式与分页非常相似,但这里的段是可变长度的,而分页页面是固定大小的。
程序段包含程序的主函数、实用函数、数据结构等。操作系统维护一个段映射表对于每个进程和空闲内存块列表以及段号、它们的大小和主内存中的相应内存位置。对于每个段,该表存储段的起始地址和段的长度。对内存位置的引用包括标识段和偏移量的值。
上一节: 操作系统 - 多线程
上一节
下一节: 操作系统 - 虚拟内存
下一节
查看笔记 分享笔记
笔记内容:
称呼:
Email:
站点:
分享笔记 重置
分类导航
前端
Ajax 教程
Angular 教程
Aurelia 教程
Bootstrap 教程
ChartJS 教程
CSS 教程
ES6 教程
FontAwesome 教程
HTML 教程
HTML 字符集 教程
HTML 游戏 教程
JavaScript 教程
jQuery 教程
Less 教程
React 教程
Sass 教程
Stylus 教程
TypeScript 教程
Unity 教程
Vue.js 教程
WebAssembly 教程
XAML 教程
颜色 教程
服务端
C# 教程
C++ 教程
COBOL 教程
C语言 教程
Fortran 教程
Go 教程
Groovy 教程
Java 教程
JSP 教程
JVM 教程
Kotlin 教程
Lisp 教程
Lua 教程
Node.js 教程
Pascal 教程
Perl 教程
PHP 教程
Python 教程
Python 3 教程
Ruby 教程
Rust 教程
Scala 教程
Spring 教程
Spring Boot 教程
Spring Cloud 教程
VB.Net 教程
移动端
Android 教程
IOS 教程
Objective-C 教程
React Native 教程
Swift 教程
小程序 教程
数据库
Access 教程
DB2 教程
Mariadb 教程
Memcached 教程
MongoDB 教程
MySQL 教程
Neo4j 教程
PL/SQL 教程
PostgreSQL 教程
Redis 教程
SQL 教程
SQL Server 教程
SQLite 教程
T-SQL 教程
数据格式
Jackson 教程
JSON 教程
SVG 教程
XML 教程
开发工具
ActiveMQ 教程
Ant 教程
Apache HttpClient 教程
Apache POI PPT 教程
AWS 教程
Docker 教程
ElasticSearch 教程
ExpressJS 教程
GIT 教程
GitLab 教程
Google Maps 教程
Gradle 教程
Java NIO 教程
JavaFX 教程
JavaMail 教程
JDBC 教程
jMeter 教程
JPA 教程
jsoup 教程
Junit 教程
KoaJS 教程
Kubernetes 教程
Log4j 教程
Logstash 教程
Lucene 教程
Makefile 教程
Maven 教程
RESTful 教程
Sed 教程
SEO 教程
Servlet 教程
SLF4J 教程
Socket.IO 教程
Struts 教程
SVN 教程
TestNG 教程
UML 教程
UNIX / LINUX 教程
WebSocket 教程
WPF 教程
xStream 教程
区块链 教程
数据处理
Flink 教程
Flume 教程
Hadoop 教程
Hbase 教程
Hive 教程
Kafka 教程
Kibana 教程
MapReduce 教程
MATLAB 教程
MyBatis 教程
Pig 教程
R语言 教程
Solr 教程
Spark 教程
Storm 教程
Zookeeper 教程
大数据分析 教程
数据仓库 教程
数据挖掘 教程
计算机基础
HTTP 教程
IPv4 教程
IPv6 教程
Ubantu 教程
WebServices 教程
嵌入式系统 教程
操作系统 教程
数据结构和算法 教程
汇编语言 教程
物联网 教程
电子电路基础 教程
编译器设计 教程
网站开发 教程
计算机 教程
计算机基础 教程
计算机网络 教程
设计模式 教程
AI
CNTK 教程
Keras 教程
PyTorch 教程
TensorFlow 教程
人工智能 教程
机器学习 教程
Python 技术
Django 教程
Flask 教程
NumPy 教程
Pandas 教程
Pillow 教程
PyGTK 教程
PyQt5 教程
PySpark 教程
pytest 教程
Python -数据科学 教程
Python MySQL 教程
Python 取证 教程
Python 数据结构 教程
Python 文本处理 教程
Python 网络编程 教程
Python 网页抓取 教程
Python 设计模式 教程
RxPY 教程
SciPy 教程
Seaborn 教程
SymPy 教程
wxPython 教程
框架
Laravel 教程
Web 图标Icon 教程
Web2py 教程
WebGL 教程
WebRTC 教程
WordPress 教程
Yii 教程
Zend Framework 教程
SAP
Crystal Reports 教程