段,页,段页,三种内存(RAM)管理机制分析

2024-06-24 09:36

本文主要是介绍段,页,段页,三种内存(RAM)管理机制分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

段,页,段页

        是为实现虚拟内存而产生的技术。直接使用物理内存弊端:地址空间不隔离,内存使用效率低。

段:就是按照二进制文件的格式,在内存给进程分段(包括堆栈、数据段、代码段)。通过段寄存器中的段表来进行虚拟地址和物理地址的转换。

段实现的虚拟地址 = 段号+offset

物理地址:被分为很多个有编号的段,每个进程的虚拟地址都有段号,这样可以实现虚实地址之间的转换。其实所谓的地址映射,就是虚实地址转换之间的那个公式。

经过上面的理解我们知道了,实现段机制的器件其实就是段寄存器(段表)

不足:内存碎片(程序结束后内存被分割为一小块一小块),解决方法是SWAP分区(将散开的进程读出来再粘贴到另一个进程边上,使空闲的内存是连贯的,但这样效率很低)

页:就是将物理内存固定大小地分为n个页(linux中是4KB一页)。通过MMU的页表来进行虚实地址转换,这里就不是用寄存器来实现了。页表记录着页号、页号对应的物理地址,比较创新的是还记录着权限。基本功能已经有了,就是物理地址和页号怎么对应上。

页实现的虚拟地址 = 页号 + 页内偏移

物理地址:被分为很多个有编号的页,每个进程的虚拟地址都是用页号和偏移来记录,通过MMU来进行虚实转换。

经过上面的理解我们知道了,实现页机制的器件其实就是MMU。

优点:为什么说MMU可以让原本1G SDRAM的物理内存,实现能够实际使用4G SDRAM空间?甚至给每个程序都安排上4G SDRAM的内容空间?为什么每一个进程的内存空间是独立的?

就是因为物理SDRAM用页来管理,有些不用的页,可以暂时先存到硬盘上,硬盘的空间就非常大了动不动就是几百个G,所以可以做到虚拟出很大的内存空间给到程序。因为每一个进程都有自己单独的页表,一个进程根本没法知道或者操作另一个进程的页表,对应的也就不知道另一个进程的地址(虚拟地址对应的物理地址)在哪里,自然就是独立的。

缺点:页表本身占用的内存太多了,每一个进程有一个页表,那么理论上32位的机器4G的物理内存,每一页是4K的话,总共会有4G/4K = 2^10 * 2*10 个页表,如果一个页表要4MB,那光是记录页表就要占用800M的内存。

解决:套娃,用多级页表。

采用多级页表机制的虚拟地址 = 一级页号 + 二级页号 + 页内偏移。这样MMU可以通过页号1来找到页号2,通过页号2+页内偏移来找到对应的物理地址从而实现虚实转换。那为啥这样能够降低页表占用内存的大小呢?其实就行把文件折叠了一样,如果一级页表里面有的二级页表没有被分配,那这些二级页表实际上就是没有分配内存的;如果有些二级页表很久没有被使用,那这些二级页表也可以暂时存到硬盘里,也不占用空间。假如一个一级页表是4MB的话,那就相当于你可以用1个4MB的内存大小去管理很多个占4MB的二级页表,然而实际只占用了4MB。照着这个思路,可以造出很多级的页表,进行极致的页表空间压缩。

缺点2:多级页表是省了空间,但是从虚拟地址转成物理地址也多了很多步骤,要一级一级地查找最终才能找到对应的物理地址。

解决2:建立快表TLB,实际就是把一些最近使用的进程它虚拟地址对应的最底层页号和偏移,存到一个一级表中(快表),这样要地址转换时,先去快表找,找不到再去查多级页表。如此就显著提高了虚实地址转换速度,而且也节省了空间。

段页式

段页式:其实就是把物理地址分为一大段一大段的,在段的内部,再进行分页。

段页式机制下虚拟地址 = 段号 + (段内)页号 + 页内偏移

这样就结合了段(契合二进制文件堆栈,代码段,数据段分层,便于程序分配地址)和页(多级页表节省空间)两个特点。

不足:就是实现起来比较复杂。但是段页式是现在内存(SDRAM)管理的主流。需要注意的是,Linux是使用页机制的。

但是linux中的页机制也一定程度上有段页结合的影子,下面是段页式的虚实地址转换流程:

linux中每一个进程虚拟地址中的段号都是对应的0~4GB的地址空间,每一个进程段空间范围都一样就意味着虚拟地址中的段号没有划分地址的作用,实际上linux中的虚拟地址是 "虚拟地址 = 段号+页号+页内偏移 ",系统有规定某些段号只有内核程序能使用,应用层程序只能使用另一些段号。从而实现了访问权限的机制。

这篇关于段,页,段页,三种内存(RAM)管理机制分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1089772

相关文章

MySQL 内存使用率常用分析语句

《MySQL内存使用率常用分析语句》用户整理了MySQL内存占用过高的分析方法,涵盖操作系统层确认及数据库层bufferpool、内存模块差值、线程状态、performance_schema性能数据... 目录一、 OS层二、 DB层1. 全局情况2. 内存占js用详情最近连续遇到mysql内存占用过高导致

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499

最新Spring Security的基于内存用户认证方式

《最新SpringSecurity的基于内存用户认证方式》本文讲解SpringSecurity内存认证配置,适用于开发、测试等场景,通过代码创建用户及权限管理,支持密码加密,虽简单但不持久化,生产环... 目录1. 前言2. 因何选择内存认证?3. 基础配置实战❶ 创建Spring Security配置文件

java内存泄漏排查过程及解决

《java内存泄漏排查过程及解决》公司某服务内存持续增长,疑似内存泄漏,未触发OOM,排查方法包括检查JVM配置、分析GC执行状态、导出堆内存快照并用IDEAProfiler工具定位大对象及代码... 目录内存泄漏内存问题排查1.查看JVM内存配置2.分析gc是否正常执行3.导出 dump 各种工具分析4.

Olingo分析和实践之EDM 辅助序列化器详解(最佳实践)

《Olingo分析和实践之EDM辅助序列化器详解(最佳实践)》EDM辅助序列化器是ApacheOlingoOData框架中无需完整EDM模型的智能序列化工具,通过运行时类型推断实现灵活数据转换,适用... 目录概念与定义什么是 EDM 辅助序列化器?核心概念设计目标核心特点1. EDM 信息可选2. 智能类

Olingo分析和实践之OData框架核心组件初始化(关键步骤)

《Olingo分析和实践之OData框架核心组件初始化(关键步骤)》ODataSpringBootService通过初始化OData实例和服务元数据,构建框架核心能力与数据模型结构,实现序列化、URI... 目录概述第一步:OData实例创建1.1 OData.newInstance() 详细分析1.1.1

Olingo分析和实践之ODataImpl详细分析(重要方法详解)

《Olingo分析和实践之ODataImpl详细分析(重要方法详解)》ODataImpl.java是ApacheOlingoOData框架的核心工厂类,负责创建序列化器、反序列化器和处理器等组件,... 目录概述主要职责类结构与继承关系核心功能分析1. 序列化器管理2. 反序列化器管理3. 处理器管理重要方

SpringBoot中六种批量更新Mysql的方式效率对比分析

《SpringBoot中六种批量更新Mysql的方式效率对比分析》文章比较了MySQL大数据量批量更新的多种方法,指出REPLACEINTO和ONDUPLICATEKEY效率最高但存在数据风险,MyB... 目录效率比较测试结构数据库初始化测试数据批量修改方案第一种 for第二种 case when第三种

解决1093 - You can‘t specify target table报错问题及原因分析

《解决1093-Youcan‘tspecifytargettable报错问题及原因分析》MySQL1093错误因UPDATE/DELETE语句的FROM子句直接引用目标表或嵌套子查询导致,... 目录报js错原因分析具体原因解决办法方法一:使用临时表方法二:使用JOIN方法三:使用EXISTS示例总结报错原

MySQL中的LENGTH()函数用法详解与实例分析

《MySQL中的LENGTH()函数用法详解与实例分析》MySQLLENGTH()函数用于计算字符串的字节长度,区别于CHAR_LENGTH()的字符长度,适用于多字节字符集(如UTF-8)的数据验证... 目录1. LENGTH()函数的基本语法2. LENGTH()函数的返回值2.1 示例1:计算字符串