在现代的层次结构中, 存储器是信息处理的来源与归宿, 占据重要位置. 但是, 在现有技术条件下, 任何一种存储装置, 都无法同时从速度与容量两方面, 满足用户的需求. 实际上它们组成了一个速度由快到慢, 容量由小到大的存储装置层次.
逻辑地址与物理地址
存储共享
存储保护与安全
内存 “扩充”
程序处理的基本过程
- 决定装入方式
程序中所使用的绝对地址, 可以编译或汇编时给出, 也可以由程序员直接赋予. 但在由程序员直接给出绝对地址时, 不仅要求程序员熟悉内存的使用的情况, 而且一旦程序或数据被修改后, 可能要改变程序中的所有地址. 因此通常是宁可在程序中采用符号地址, 然后再编译或汇编时, 在将这些符号地址转化为绝对地址
- 可重入定位装入方式
静态可重定位装入方式和动态可重定位装入方式
静态可重定位装入方式不允许程序在装入之后的运行过程中发生内存位置的移动
动态可重定位装入方式及动态重定位过程通常需要一定的硬件机构支持以使地址转换不影响指令执行速度.
- 动态运行时装入方式
动态运行时的装入程序, 在把装入模块转入内存后, 并不立即把装入模块中的相对地址转换为绝对地址, 而是把这种地址转换推辞到程序真正要执行时才进行
- 静态链接方式
- 装入时动态链接
- 运行时动态链接
这种链接方式是将对某些模块的链接推迟到执行时才执行, 即, 在执行过程中,当发现一个被调用模块尚未装入内存时, 立即由 OS 去找到该模块并将之装入内存, 把它链接到调用者模块上. 凡在执行过程中未被用到的目标模块, 都不会被调入内存和链接到装入内存, 这样不仅可加快程序的装入过程, 而且可节省大量内存空间
把作业地址空间中使用的逻辑地址变为内存空间中的物理地址的过程, 又称为地址 映射
- 重定位的类型
静态重定位: 当用户程序被装入内存时一次性实现逻辑地址到物理地址的转换, 以后不在转换(一般在装入内存时由软件完成) 作业i在执行前一次变址, 直到该作业完成退出内存为止.
动态重定位
在程序运行过程中药访问数据时再进行地址变换, 由地址变换机构进行的地址变换, 硬件上需要重定位寄存器的支持
连续内存分配: 每个进程位于一个连续的内存空间
工作流程
单一连续区分配采用静态分配和静态重定位方式, 即作业或进程一旦进入主存, 就一直等到它运行结束后才能释放主存
存储保护
分区式管理是满足多道程序的最简单的存储管理方案。它的基本思想是将内存划分若干个连续区域,称为分区。分区只能存储一个程序,而程序也只能在它所驻留的分区中运行。
- 固定分区
预先把可分配的主存储区空间分割成若干个连续区域, 称为一个分区. 每个分区的大小可以相同也可以不同. 但分区大小固定不变, 每个分区装一个且只能装一个作业
存储分配: 如果有一个空闲区, 则分配给进程
- 内存分配管理
通过设置内存分配表, 内存分配简单
缺点: 内存利用率不高
- 分区分配中的数据结构
(1) 空闲分区链
系统设立空闲分区链表: 每个空闲块的前后两个单元, 放置必要的说明信息和指针. 系统只要设立一个链首指针, 指向第一个空闲块即可. 分配程序可以依照自由块链表, 来查找合适的空闲块进行分配
(2) 分区分配表
- 分区分配操作
(1) 分配内存
(2) 回收内存
- 分配算法
按空闲块链接的方式不同, 可以有以下四种算法:
- 碎片问题
碎片问题的解决
- 分区式存储管理的优缺点
2. 动态重定位的实现
4.可重定位分区的优缺点
以上讨论都是基于一个作业在主存中占据的是一个连续分区的假定, 为了支持结构化程序设计, 操作系统往往把一道作业分成若干片段(如子程序, 主程序, 数据组等). 这样, 片段之间就不需要连续了, 只要增加一些重定位寄存器, 就可以有效地控制一道作业片段之间的调用
为了防止一首作业有意或无意地破坏操作系统或其它作业. 一般来说, 没有硬件支持, 实现有效的存储保护是困难的. 通常采用:
保护过程 – 防止地址越界
基址寄存器: 存放起始地址
限长寄存器: 存放长度
界限寄存器保护
基址、限长寄存器保护
防止操作越权
对于允许多个进程共享的存储区域,每个进程都有自己的访问权限。如果一个进程对共享区域的访问违反了权限规定,则发生操作越权 即读写保护
保护键方式
- 页面和物理块
分页存储管理, 是将一个进程的逻辑地址空间分成若干个大小相等的片, 称为 页面或页, 并为各页加以编号. 相应的, 也把内存空间分成与页面相同大小的若干个存储块, 称为(物理)块或页框.
分页管理中页与页框的对应关系示意图
- 地址结构
分页地址中的地址结构如下:
对某特定机器, 其地址结构是一定的, 若给定一个逻辑地址空间的地址A, 页面的大小为L, 则页号P和页内地址d可按下式求得:
- 管理
页表
空快管理
内存的分配与回收
位示图法
为了找到N个自由块, 就需要搜索位示图, 找到N个 “0” 位, 再经过一个简单的运算就得知相应的快地址(物理地址), 存贮空间的分配和回收工作较为方便, {0,1} 转换.
盘块的分配
盘块的回收
内存的分配
- 快表
如果把页表放在主存中, 无疑会影响系统的性能, 这是因为每次访问主存, 首先必须访问页表, 读出页描述子, 之后根据形成的实际地址在访问主存, 这要使访问主存的次数加倍, 因而使总的处理速度明显下降.
为了解决这个问题, 人们采用一组硬件寄存器, 存放当前访问过的页的页描述子, 每次访问主存时, 首先查找快表, 若找到所需的页描述子, 则快速形成物理地址. 否则从页表中查找后形成物理地址, 同时把页描述子写入快表. 如果设计得到, 快表的命中率可以很高
现代的大多数计算机系统, 都支持非常大的逻辑地址空间( 2 32 2^{32} 232 ~ 2 64 2^{64} 264). 页表就变得非常大, 要占用相当大的内存空间. 可采用两个方法来解决这一问题: ① 采用离散分配方式来解决难以找到一块连续的大内存空间的问题; ② 只将当前需要的部分页表项调入内存, 其余的页表项仍驻留在磁盘上, 需要时再调入.
- 两级级页表
32 位 进程页表多大?
设: 页面大小为: 4K, 用户空间 4GB
则: 一个进程 1M 页
设: 每个内存块号 4 字节
则: 进程页表 1K 页, 共占 4M 内存空间
结论: 一个进程的页表的各页之间可以不用连续存放
解决: 页表本身使用地址索引 – 页目录
- 多级级页表
64位 进程页表多大?
设: 页表大小为4K
则: 一个进程 2 52 2^{52} 252 页
设: 每个内存块号 4字节
则: 进程页表 2 42 ( 2 52 ÷ 2 10 ) 2^{42} (2^{52} \div 2^{10}) 242(252÷210) 页, 两级页表不能接受
结论: 必须采用三级以上的多级页表
- 反置页表
在分页存储管理系统重, 作业的地址空间是一维线性的, 这破坏了程序内部天然的逻辑结构, 造成共享, 保护的困难. 引入分段存储管理方式, 主要是为了满足用户和程序的下述需要:
- 段表
- 硬件支持
- 地址变换机构
- 分页和分段的主要区别
分段管理的优缺点
产生背景: 结合了段式与页式二者优点, 克服了二者的缺点
基本思想
用户程序划分: 按段式划分 (对用户来讲, 按段的逻辑关系进行划分; 对系统讲, 按页划分每一段)
内存划分: 按页式存储管理方案
内存分配: 以页为单位进行分配
- 管理
- 地址空间和地址结构
一个程序首先被划分成若干程序段, 每一段给予不同的分段标识符然后, 对每一分段又分成若干个固定大小的页面. 系统中的一个作业的地址空间结构页面尺寸为 4 K 字节, 该作业有三个分段, 第一段为 15K 字节, 占 4 页, 最后一页只有 1K 未用; 其他段同理. 未足一页大小的补为一页.
5.地址映射
- 地址变换
上述的地址变换要访问主存三次, 这将执行程序的速度大大降低, 为了解决上述问题, 可以采取"快表"技术
当内存空间紧张时, 系统将内存中某些进程暂时移到外存, 把外存中某些进程换进内存, 占据前者所占用的区域, 这种技术是进程在内存于外存之间的动态调度. 多用于分时系统中
何时需发生交换?
例子:
需要一个盘交换区: 必须足够大一存放所有用户程序的所有内存映象的拷贝; 必须对这些内存映象的直接存取
问题的提出:
虚拟存储器的基本思想是: 程序, 数据, 堆栈的大小可以超过内存的大小, 操作系统把程序当前使用的部分保留在内存, 而把其它部分保存在磁盘上, 并在需要时在内存和磁盘之间动态交换
虚拟存储器支持多到程序设计技术
程序局部性原理
在一段时间内一个程序的执行往往呈现出高度的局部
文章浏览阅读3.8k次,点赞9次,收藏28次。直接上一个工作中碰到的问题,另外一个系统开启多线程调用我这边的接口,然后我这边会开启多线程批量查询第三方接口并且返回给调用方。使用的是两三年前别人遗留下来的方法,放到线上后发现确实是可以正常取到结果,但是一旦调用,CPU占用就直接100%(部署环境是win server服务器)。因此查看了下相关的老代码并使用JProfiler查看发现是在某个while循环的时候有问题。具体项目代码就不贴了,类似于下面这段代码。while(flag) {//your code;}这里的flag._main函数使用while(1)循环cpu占用99
文章浏览阅读347次。idea shift f6 快捷键无效_idea shift +f6快捷键不生效
文章浏览阅读135次。Ecmacript 中没有DOM 和 BOM核心模块Node为JavaScript提供了很多服务器级别,这些API绝大多数都被包装到了一个具名和核心模块中了,例如文件操作的 fs 核心模块 ,http服务构建的http 模块 path 路径操作模块 os 操作系统信息模块// 用来获取机器信息的var os = require('os')// 用来操作路径的var path = require('path')// 获取当前机器的 CPU 信息console.log(os.cpus._node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是
文章浏览阅读10w+次,点赞435次,收藏3.4k次。SPSS 22 下载安装过程7.6 方差分析与回归分析的SPSS实现7.6.1 SPSS软件概述1 SPSS版本与安装2 SPSS界面3 SPSS特点4 SPSS数据7.6.2 SPSS与方差分析1 单因素方差分析2 双因素方差分析7.6.3 SPSS与回归分析SPSS回归分析过程牙膏价格问题的回归分析_化工数学模型数据回归软件
文章浏览阅读7.5k次。如何利用hutool工具包实现邮件发送功能呢?1、首先引入hutool依赖<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.19</version></dependency>2、编写邮件发送工具类package com.pc.c..._hutool发送邮件
文章浏览阅读867次,点赞2次,收藏2次。docker安装elasticsearch,elasticsearch-head,kibana,ik分词器安装方式基本有两种,一种是pull的方式,一种是Dockerfile的方式,由于pull的方式pull下来后还需配置许多东西且不便于复用,个人比较喜欢使用Dockerfile的方式所有docker支持的镜像基本都在https://hub.docker.com/docker的官网上能找到合..._docker安装kibana连接elasticsearch并且elasticsearch有密码
文章浏览阅读1.3w次,点赞57次,收藏92次。整理 | 郑丽媛出品 | CSDN(ID:CSDNnews)近年来,随着机器学习的兴起,有一门编程语言逐渐变得火热——Python。得益于其针对机器学习提供了大量开源框架和第三方模块,内置..._beeware
文章浏览阅读7.9k次。//// ViewController.swift// Day_10_Timer//// Created by dongqiangfei on 2018/10/15.// Copyright 2018年 飞飞. All rights reserved.//import UIKitclass ViewController: UIViewController { ..._swift timer 暂停
文章浏览阅读986次,点赞2次,收藏2次。1.硬性等待让当前线程暂停执行,应用场景:代码执行速度太快了,但是UI元素没有立马加载出来,造成两者不同步,这时候就可以让代码等待一下,再去执行找元素的动作线程休眠,强制等待 Thread.sleep(long mills)package com.example.demo;import org.junit.jupiter.api.Test;import org.openqa.selenium.By;import org.openqa.selenium.firefox.Firefox.._元素三大等待
文章浏览阅读3k次,点赞4次,收藏14次。Java软件工程师职位分析_java岗位分析
文章浏览阅读2k次。Java:Unreachable code的解决方法_java unreachable code
文章浏览阅读1w次。1、html中设置标签data-*的值 标题 11111 222222、点击获取当前标签的data-url的值$('dd').on('click', function() { var urlVal = $(this).data('ur_如何根据data-*属性获取对应的标签对象