操作系统内存地址映射

2023-10-07 03:10

本文主要是介绍操作系统内存地址映射,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

内存管理的机制

这里主要是做个知识点的记录,方便以后查看

内存是现代计算机的运行的中心,内存是由很大的一组字或者是字节组成的,每个字或者是字节都是有它们自己的地址,以及CPU会根据程序计数器(PC)的值从内存中提取指令,这些指令可能会引起进一步对特定内存地址的读取和写入

在一个典型的指令执行周期当中,首先会从内存中去读取指令。接着这个指令被解码,以及可能需要从内存中读取操作数,在指令对操作数执行之后,其的结果可能被存到内存中

需要注意的是CPU能直接访问的存储器只有内存和处理器内的寄存器,机器指令可以用内存地址作为参数,但是不能用磁盘的地址作为参数,所以其实CPU在执行指令的时候一定要保证所要用的数据在CPU可以直接访问的存储设备当中

CPU的内置寄存器通常可以在一个CPU的时钟周期当中完成访问,对于寄存器当中的内容,绝大多数CPU可以在一个时钟周期内去解析并且去执行一个或者是多个指令,但是对于内存的访问则是可能需要多个CPU的时钟周期,而CPU执行有些指令的时候是需要数据的,如果没有数据的话有些指令就执行不了,所以CPU的效率就会受到影响,所以为了解决内存访问频繁的情况,解决方法就是在CPU和内存之间去增加高速内存,这种协调速度差异的内存的缓冲区被称为是高速缓存

我们除了去保证访问物理内存的相对的速度之外,我们还要确保操作系统所在的内存空间不被用户的进程所访问,以及确保用户进程不被其他用户进程访问,这种保护可以通过硬件来实现,方法有多种,这里就介绍一种可能的情况

为了确保每个进程都有独立的内存空间,所以我们需要去确定进程可访问的合法地址的范围,并且确保进程只访问其的合法地址,我们可以通过两个寄存器拿来当做基地址寄存器以及界限地址寄存器,基地址寄存器当中包含最小的合法物理内存地址,界限地址寄存器决定了范围的大小,就比如说如果基地址寄存器中是3000,界限地址寄存器中是1000,那么程序可以访问的内存地址范围就为3000-4000。这种内存空间的保护是通过CPU硬件对用户模式所产生的每一个地址与寄存器的地址进行比较来完成的,如果说用户模式下要去访问操作系统的内存和其他用户进程的内存就会报错

关于内存地址的访问范围
这里写图片描述

在上述的保护模式下,只有操作系统可以通过特殊的特权指令去加载基地址寄存器和界限地址寄存器,所以用户进程是无法改变的,只有操作系统可以去修改基地址寄存器和界限地址寄存器的值,操作系统在内核模式下执行,可以无限制的去访问操作系统和用户的内存,所以操作系统可以将用户程序装入用户内存,在出错的时候输出这些程序,访问并修改系统调用的参数等

通常情况下,程序以二进制可执行文件的形式存储在磁盘上,为了执行,程序被调入内存并放在进程空间内。根据所使用的内存管理方案,进程在执行时可以在磁盘和内存之间进行移动,在磁盘上等待调入内存以便执行的进程形成输入队列

一般来说用户程序在执行前,需要经过好几个步骤(如下图所示),其中有些是可选的,在这些步骤当中地址可能有不同的表示形式,源程序中的地址

这里写图片描述

通常我们将指令和数据绑定到内存地址有以下的几种情况

  • 编译时:如果在编译的时候就知道进程将在内存当中的驻留地址,那么就可以生成绝对的代码,比如说我们事先就知道用户进程驻留在内存地址1000,那么所生成的编译的代码就可以从该位置开始往后扩展
  • 加载的时候,如果编译的时候并不知道进程将驻留在内存的什么地方,那么编译器就必须去生成可重定位的代码,对于这种情况的话,由于源程序中的地址通常是用符号来表示的(比如a),这样的话编译器通常会将这些符号地址绑定在可重定位的地址(比如说从本模块开始的第14个字节),然后加载程序再将这些可重定位的地址去绑定成绝对地址
  • 执行时,如果进程在执行时可以从一个内存段转移到另一个内存段,那么绑定就必须延迟到执行时才会进行,这个绑定就是指的是绑定成绝对的地址,采用这种方案是需要特定的硬件的,绝大多数通用计算机操作系统采用这种方法

逻辑地址空间与物理地址空间

CPU生成的地址通常称为逻辑地址,而加载到内存地址寄存器的被称为物理地址,运行时从虚拟地址到物理地址的映射是被称为内存管理单元的硬件设备来完成的

从虚拟地址到物理地址的映射我们可以通过去使用重定位寄存器,就是说用户进程所生成的地址在递交内存之前,都会加上重定位寄存器的值,就比如说如果说重定位寄存器当中的值为14000,然后我们用户对用户进程位置0的访问就会动态地重定位为14000,对地址346的访问就会将其映射为14345,运行于Intel 80x86系列的CPU的MS-DOS操作系统在加载和运行进程的时候,就可以使用4个重定位地址寄存器

内存管理单元利用重定位寄存器做的地址映射

这里写图片描述

这篇关于操作系统内存地址映射的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

C++高效内存池实现减少动态分配开销的解决方案

《C++高效内存池实现减少动态分配开销的解决方案》C++动态内存分配存在系统调用开销、碎片化和锁竞争等性能问题,内存池通过预分配、分块管理和缓存复用解决这些问题,下面就来了解一下... 目录一、C++内存分配的性能挑战二、内存池技术的核心原理三、主流内存池实现:TCMalloc与Jemalloc1. TCM

Redis过期删除机制与内存淘汰策略的解析指南

《Redis过期删除机制与内存淘汰策略的解析指南》在使用Redis构建缓存系统时,很多开发者只设置了EXPIRE但却忽略了背后Redis的过期删除机制与内存淘汰策略,下面小编就来和大家详细介绍一下... 目录1、简述2、Redis http://www.chinasem.cn的过期删除策略(Key Expir

Java内存区域与内存溢出异常的详细探讨

《Java内存区域与内存溢出异常的详细探讨》:本文主要介绍Java内存区域与内存溢出异常的相关资料,分析异常原因并提供解决策略,如参数调整、代码优化等,帮助开发者排查内存问题,需要的朋友可以参考下... 目录一、引言二、Java 运行时数据区域(一)程序计数器(二)Java 虚拟机栈(三)本地方法栈(四)J

java变量内存中存储的使用方式

《java变量内存中存储的使用方式》:本文主要介绍java变量内存中存储的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍2、变量的定义3、 变量的类型4、 变量的作用域5、 内存中的存储方式总结1、介绍在 Java 中,变量是用于存储程序中数据

在Spring Boot中浅尝内存泄漏的实战记录

《在SpringBoot中浅尝内存泄漏的实战记录》本文给大家分享在SpringBoot中浅尝内存泄漏的实战记录,结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录使用静态集合持有对象引用,阻止GC回收关键点:可执行代码:验证:1,运行程序(启动时添加JVM参数限制堆大小):2,访问 htt

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

Redis 内存淘汰策略深度解析(最新推荐)

《Redis内存淘汰策略深度解析(最新推荐)》本文详细探讨了Redis的内存淘汰策略、实现原理、适用场景及最佳实践,介绍了八种内存淘汰策略,包括noeviction、LRU、LFU、TTL、Rand... 目录一、 内存淘汰策略概述二、内存淘汰策略详解2.1 ​noeviction(不淘汰)​2.2 ​LR

Golang基于内存的键值存储缓存库go-cache

《Golang基于内存的键值存储缓存库go-cache》go-cache是一个内存中的key:valuestore/cache库,适用于单机应用程序,本文主要介绍了Golang基于内存的键值存储缓存库... 目录文档安装方法示例1示例2使用注意点优点缺点go-cache 和 Redis 缓存对比1)功能特性

Go使用pprof进行CPU,内存和阻塞情况分析

《Go使用pprof进行CPU,内存和阻塞情况分析》Go语言提供了强大的pprof工具,用于分析CPU、内存、Goroutine阻塞等性能问题,帮助开发者优化程序,提高运行效率,下面我们就来深入了解下... 目录1. pprof 介绍2. 快速上手:启用 pprof3. CPU Profiling:分析 C

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内