19.段页结合的实际内存管理

【README】

1.本文内容总结自 B站 《操作系统-哈工大李治军老师》,内容非常棒,墙裂推荐;

2.段与页

  • 段: 用户程序采用分段结构;
  • 页: 操作系统采用分页机制管理物理内存;
  • 段页结合:程序员希望用段,物理内存希望用页,所以操作系统需要把段与页结合起来管理内存;

3.段页各自工作机制

问题:如何把 分段式内存管理 与  分页式内存管理 联系起来?


【1】虚拟内存

1)虚拟内存定义

  • 操作系统用程序实现了虚拟内存,把段与页结合起来;如下图所示。

 【图解】

  • 从用户视角,程序分段存储;
  • 从物理内存视角,内存按照分页管理;

2)段页同时存在:段面向用户/页面向硬件

【图解】
用户程序分段存储在虚拟内存,包括数据段,代码段等;
以用户代码段为例:
把用户代码段分为3个内存页进行存储,其中某段的虚拟地址为0x00345008,映射的物理地址是 0x7008;
补充:

  • 虚拟内存的代码段基址存储在cs段寄存器中,偏移量存储在ip寄存器中;

【2】 段页同时存在时的重定位(地址翻译)

0)背景

  • 上述介绍了通过分段,每段分页把程序存储到多个内存页;
  • 为了让用户使用内存,还应该提供段页同时存在时的重定位功能(逻辑地址翻译为物理地址的功能)

1)段页同时存在时的重定位(重定位也称为地址翻译,逻辑地址翻译为物理地址)

 

【图解】

  • 步骤1:获取程序逻辑地址,结构为 段号+偏移,分别用cs : ip 存储段号,偏移量;
  • 步骤2:根据段号从段表中查询段基址,这个段基址是虚拟地址
  • 步骤3:根据虚拟地址计算出页号(如虚拟地址0x1756的页号为17);
  • 步骤4:根据页号从页表中查询出页框号(物理页号),如页框号为3;
  • 步骤5:根据页框号(物理页号)和页内偏移计算出物理内存地址,如0x0356;至此完成了逻辑地址到物理内存地址的翻译;

最后:操作系统把物理内存地址送入地址总线读写该内存地址上的数据;

【小结】段页同时存在时的重定位(地址翻译)

  • 从逻辑地址映射到虚拟地址,虚拟地址映射到物理地址的过程;
  • 操作系统基于以上2层地址映射,实现既面向用户支持分段,又面向物理内存支持分页管理;
  • 所以构成了段页结合的内存管理模式,其核心在于虚拟内存

【3】 段页时结合的内存管理示例

内存管理的核心就是内存分配,所以从程序放入内存,使用内存开始(使用内存就是取指执行);

【3.1】段页时内存管理具体措施

1)具体措施

  • 分配段,建立段表;
  • 分配页,建立页表;
  • 进程带动内存使用的图谱(给进程分配了内存后,进程中的程序就可以放入内存);
  • 从进程fork中的内存分配开始;(进程fork,创建一个新进程,也就需要为新进程分配内存空间,使得程序中的逻辑地址能够正确翻译到物理地址)

 2)段页式内存下程序如何载入内存?

  • 步骤1:建立段表:把用户程序段(如代码段,数据段)与虚拟地址中的段映射起来;如在虚拟内存上分割一段区域分配给用户数据段,以此建立映射关系,即建立段表;
    • 如何分割? 采用分区算法对虚拟内存进行分割(只需要存储分区基址和长度);
  • 步骤2:建立页表:把虚拟地址中的段分割为若干逻辑页,如3个逻辑页;3个逻辑页与物理内存的3个物理页进行映射,即建立页表;

补充:虚拟内存是不存在的,是操作系统用程序实现的

3)段页式内存下程序载入内存的示意图如下:

【图解】
虚拟地址段表结构(采用分区算法分割虚拟内存,如最佳适合分区算法,分区算法需要存储基址和长度): 

段号

基址(虚拟地址)

长度

保护

0

Xxx

Xx

xx

1

0x45000

60K

R/W

页表结构:

逻辑页号

页框号(物理页)

保护

Xx

xx

xx

......

......

......

0x45

7

R/W

3.1)逻辑地址:

  • 段号+偏移地址,分别通过 cs 和 ip寄存器来给出;

3.2)逻辑地址(如数据段 :  0x300)翻译为物理地址的步骤如下:

  • 根据cs获取段号(数据段的段号); (cs是代码段寄存器)
  • 根据段号查询段表得到段基址(虚拟地址) ;
  • 根据虚拟地址计算出逻辑页号;如虚拟地址0x45000,它的逻辑页号是0x45;
  • 根据逻辑页号查询页表得到页框号(物理页号);如根据逻辑页号45得到物理页号7;
  • 根据物理页号7和偏移地址(ip寄存器个给出,如0x300)得到最终的物理内存地址0x7300; 即数据段中的指令 mov [300],0 中的逻辑地址300翻译后的物理地址为 0x7300 (把0赋值给物理地址0x7300内存单元)

地址翻译(重定向)完成后,操作系统把物理地址送入地址总线以读写该地址上的数据;


【4】段页式内存管理代码实现

【4.1】分配虚拟内存,建立段表  (第1步)

 【代码解说】

  • copy_process函数: 创建新进程;
  • copy_mem函数:新进程的内存与当前进程的内存分配情况相同;
  • 补充:LDT表就存储了该程序多个段的段基址;

1)copy_mem代码(分配虚拟内存,建立段表):

int copy_mem(int nr, task_struct *p)
{unsigned long new_data_base;// new_data_base就是虚拟内存基址,实际上是对虚拟内存的分割;每个新进程的虚拟内存空间是64M; // 0号进程的虚拟内存空间是0~64M-1;1号进程的虚拟内存空间是 64M~2*64M-1;...... new_data_base = nr * 0x4000000;  // 64M * nr ,nr是第几个进程 // 建立段表,为段表的代码段设置基址;p是pcb;进程切换时,段表跟着切换;set_base(p->ldt[1], new_data_base); // 建立段表,为段表的数据段设置基址;p是pcb;进程切换时,段表跟着切换;set_base(p->ldt[2], new_data_base);  
} 

1.1)各进程的虚拟地址
每个进程占用 64M 的虚拟地址空间,互不重叠

 


【4.2】分配物理内存,建立页表 (第2步)

1)copy_mem 拷贝内存代码 (详细步骤)

// 拷贝内存  
int copy_mem(int nr, task_struct *p)
{unsigned long old_data_base;old_data_base = get_base(current->ldt[2]);// copy_page_tables的作用是把旧进程物理页赋值给新进程,两者使用相同的物理页 // 新进程共用旧进程的物理页, old_data_base,new_data_base分别是父进程,新进程的虚拟地址基址; // 拷贝页表,修改虚拟地址,为新进程建立页表copy_page_tables(old_data_base, new_data_base, data_limit); 
}// 拷贝页表,修改虚拟地址,为新进程建立页表 
int copy_page_tables(unsigned long from, unsigned long to, long size)
{// 位运算得到父进程的页目录号指针 from_dir ;from_dir = (unsigned long *) ( (from>>20) & 0xffc );// 位运算得到新(子)进程的页目录号指针 to_dir ;   	to_dir = (unsigned long *) ( (to >> 20) & 0xffc );// 拷贝的字节数size = (unsigned long) (size + 0x3fffff) >> 22;// for (; size-- > 0; from_dir++, to_dir++) {// from_page_table 是父进程页表基址from_page_table = (0xfffff000 & *from_dir);// 申请(分配)一个物理内存页 to_page_table = get_free_page();// 把新的物理内存页基址赋值给 to_dir *to_dir = ( (unsigned long) to_page_table ) | 7 ; 		}
}

 

2)from_page_table 与 to_page_table 

 

【图解】

  • from_dir 是页目录号 1 的基址,是 父进程 的页目录号的基址;
  • to_dir 是页目录号 7 的基址,是 子进程 的页目录号的基址;
  • 接下来要做的就是,把 from_dir 页目录号1映射的页表内容 拷贝到 to_dir页目录号7的页表;

2)把from_dir 对应的页表内容 拷贝到 to_dir 对应的页表

 【代码】父进程页表内容拷贝到子进程页表的代码如下:

// 父进程页表内容拷贝到子进程页表的代码
for(; nr-- >0; from_page_table++; to_page_table++) 
{// from_page_table 是父进程页表(基址)this_page = *from_page_table;this_page &= ~2; // 只读 // 把父进程页表 from_page_table 内容拷贝给子进程页表 to_page_table // 即 父进程页表基址 与 子进程页表基址相同,两者指向了同一块物理内存 *to_page_table = this_page; *from_page_table = this_page;this_page -= LOW_MEM;this_page >>= 12; // 当前页被共享了,所以该页的mem_map 累加; mem_map[this_page]++; 
} 

说明:

  • 这里没有为子进程重新申请物理页,这里子进程使用了父进程的物理页(当然是可以重新分配 的);

【4.3】进程建立完成后样子(fork后)

 

【图解】

  • 进程1是父进程,进程2是子进程,通过进程1 fork 出了 进程2
  • 进程2的虚拟内存和段表初始化好了;
  • 进程2的物理内存和页表也有了,即使进程2与父进程(进程1)的页表内容相同,共享同一块物理内存;
  • 根据图也可以看到,进程1的段表与进程2的段表指向了同一个物理内存基址;
  • 也就可以说,一个子进程被载入到内存中了; 尽管子进程用的代码,数据都是父进程的;

【5】程序使用内存

1)MMU

  • 内存管理单元,是一个硬件,自动完成逻辑地址到物理地址的翻译,即完成了从逻辑地址0x300到虚拟地址0x400300,再到物理地址0x7300的地址转换(用MMU硬件代替软件来实现地址翻译);

2)进程1的逻辑地址 0x300 翻译为物理地址0x7300的步骤:

  • 步骤1: 通过0x300所在程序的段号,从段表中查询出段基址0x400000(64M为基址),从而计算出0x300在虚拟内存的逻辑地址为 0x400300;
  • 步骤2:通过段基址计算得到逻辑页号,通过逻辑页号查询页表得到物理内存页号为7;
  • 步骤3: 通过物理内存页号7和偏移地址300得到物理地址 0x7300;

3)地址翻译完成后,进程1 fork出了进程2
其中,进程2 翻译逻辑地址 0x300 的步骤如下:

  • 步骤1: 通过0x300所在程序的段号,从段表中查询出段基址0x800000(128M为基址),从而计算出0x300在虚拟内存的逻辑地址为 0x800300;
  • 步骤2:通过段基址计算得到逻辑页号,通过逻辑页号查询页表得到物理内存页号为7(因为进程2与进程1的页表相同);
    • 又在进程fork时,进程1(父进程)把物理内存页7设置为只读(参见父进程页表内容拷贝到子进程页表的代码)。所以进程2无法写入内存页7,只能重新申请一个新的物理内存页,如物理页8.
  • 步骤3: 进程2得到的物理内存页号为8,与偏移量合并计算得到物理内存地址为 0x8300;

至此:父子进程通过不同的虚拟内存空间实现了相互分离,相互独立;


【补充】MMU介绍 from wikipedia

refer2  https://zh.m.wikipedia.org/zh-hans/%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86%E5%8D%95%E5%85%83

内存管理单元(英语:memory management unit,缩写为MMU),有时称作分页内存管理单元(英语:paged memory management unit,缩写为PMMU)。

它是一种负责处理中央处理器(CPU)的内存访问请求的计算机硬件它的功能包括虚拟地址到物理地址的转换(即虚拟内存管理)[1]、内存保护、中央处理器高速缓存的控制,在较为简单的计算机体系结构中,负责总线的仲裁以及存储体切换(bank switching,尤其是在8位的系统上)。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/329442.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python中变量怎么定义_python中的变量的使用定义以及使用规则

本篇包括14章内容,系统介绍了Python语言的基础知识。内容包括Python基础语法、数据类型和类型转换、运算符、流程控制(分支结构循环结构)、数据结构(列表生成式)、函数的定义及使用、异常处理、迭代器生成器、偏函数、python中的模块和包、python标准内置库os以及使…

Oracle入门(十二G)之序列

序列(SEQUENCE)序列是一数据库对象,利用它可生成唯一的整数。由于它属于可共享对象,所以允许多个用户访问。一般情况下,序列用于创建主键值。 序列号的存储和生成与表无关。因此,同一序列可以用于多个表。 …

20.内存换入-请求调页

【README】 1.本文内容总结自 B站 《操作系统-哈工大李治军老师》,内容非常棒,墙裂推荐; 2.操作系统关于内存管理的核心是基于虚拟内存的分段和分页管理; 3.而用内存换入和换出实现虚拟内存 ; 【1】虚拟内存 1&…

机器人点焊枪接线_用于焊接机器人焊枪工具点及工件坐标系标定装置及方法与流程...

本发明属于机器人焊接技术领域,涉及一种用于焊接机器人焊枪工具点及工件坐标系标定的装置及方法。背景技术:工业机器人是实施自动化生产线、工业4.0、智能制造车间、数字化工厂、智能工厂的重要基础装备之一。而据不完全统计,全世界在役的工业…

采用EntityFramework.Extended 对EF进行扩展(Entity Framework 延伸系列2)

前言 今天我们来讲讲EntityFramework.Extended 首先科普一下这个EntityFramework.Extended是什么,如下: 这是一个对Entity Framework进行扩展的类库. 完全支持EF 5.0/6.0, GitHub地址 https://github.com/loresoft/EntityFramework.Extended, 最后一次更…

Oracle入门(十二J)之同义词

转载自 oracle同义词 一、创建同义词 --普通用法 create [or replace] [public] synonym [schema.] 同义词名称 for [schema.] object [dblink];--创建专有(私有)同义词 create synonym sysn_test for test;--创建公共同义词 create public synonym publ…

21.内存换出

【README】 1.本文内容总结自 B站 《操作系统-哈工大李治军老师》,内容非常棒,墙裂推荐; 2.有内存换入就有内存换出。 3.因为物理内存空间有限,n次(第n页)换入后导致物理内存用完,则n1次&…

antd vue表单上传文件_vue+axios+antD的上传图片踩坑

一开始使用了实验室大佬封装的axios结合formData进行图片上传,然而传递给后台的formData是空的,打印出来的form又确实是存在的,百度搜了一大推,于是借鉴了百度的做法。1.引入axios import axios from ‘axios‘;2.创建一个新的axios,const …

移动web开发调试工具AlloyLever介绍

简介 web调试有几个非常频繁的刚需:看log、看error、看AJAX发包与回包。其他的如timeline和cookie以及localstorage就不是那么频繁,但是AlloyLever都支持。如你所见: 特征 点击alloylever按钮之间切换显示或隐藏工具面板Console会输出所有用户…

Oracle入门(十三A2)之单行函数

一、函数介绍 功能:改变数据输出形式或进行数据运算输出二、单行函数函数格式 函数说明abs(n) 返回n的绝对值floor(n) 返回小于等于n的最大整数ln(n) 返回n的自然对数&#xff…

22.IO与显示器

【README】 1.本文内容总结自 B站 《操作系统-哈工大李治军老师》,内容非常棒,墙裂推荐; 2.显示器是输入型外设; 3.本章主要内容是讲 显示器是如何被驱动的;或操作系统是如何让用户来使用显示器的; 4.Pri…

d3 i5 神舟精盾k480n_神舟精盾k480n i5 d3和精盾i5 d1哪个好?

(这是D3的数据)主板芯片组IntelHM76CPU系列英特尔酷睿i53代系列CPU型号Intel酷睿i53210MCPU主频2.5GHz最高睿频3100MHz总线规格DMI5GT/s三级缓存3MB核心类型IvyBridge核心/线程数双核...(这是D3的数据)主板芯片组Intel HM76CPU系列英特尔 酷睿i5 3代系列CPU型号Intel 酷睿i5 32…

[开源 .NET 跨平台 数据采集 爬虫框架: DotnetSpider] [一] 初衷与架构设计

一 ,为什么要造轮子 有兴趣的同学可以去各大招聘网站看一下爬虫工程师的要求,大多是JAVA,PYTHON甚至于还有NODEJS,C,再或者在开源中国查询C#的爬虫,仅有几个非常简单或是几年没有更新的项目。从我看的一些文…

Oracle入门(十三B)之高级查询(上)

下章:Oracle入门(十三C)之高级查询(下) 一、多表格查询 (1)定义将两个或两个以上的表格,按照一定的关系连接起来进行查询。(2)多表格查询分类 连接查询嵌套查…

23.键盘

【README】 1.本文内容总结自 B站 《操作系统-哈工大李治军老师》,内容非常棒,墙裂推荐; 2.键盘 是输出型外设; 【1】外设工作原理 【图解】外设工作原理: 步骤1:Cpu向外设控制器发出指令(如…

like左匹配索引失效_Mysql索引失效的情况

一、前提条件1、创建三张测试表:DROP TABLE IF EXISTS user;CREATE TABLE user (idint(11) NOT NULL,name varchar(25) DEFAULT NULL,ageint(11) NOT NULL DEFAULT 0,update_time datetime DEFAULT NULL,first_name varchar(25) DEFAULT NULL,last_name varchar(25)…

基于DDDLite的权限管理OpenAuth.net 1.0版正式发布

距离上一篇OpenAuth.net的文章已经有5个多月了,在这段时间里项目得到了很多朋友的认可,开源中国上面的Star数接近300,于是坚定了我做下去的信心。最近稍微清闲点,正式推出1.0版,并在阿里云上部署了一个在线演示&#x…

24.原生磁盘的使用

【README】 1.本文内容总结自 B站 《操作系统-哈工大李治军老师》,内容非常棒,墙裂推荐; 2.磁盘操作抽象 第1层抽象:通过盘块号读写磁盘(或逻辑盘块号);第2层抽象:用队列缓存多个…

Oracle入门(十三C)之高级查询(下)

上章:Oracle入门(十三B)之高级查询(上) 四、常见组函数 SUM、AVG、COUNT、MIN、MAX分组函数忽略null 值。不能在WHERE 子句中使用组函数。MIN 和MAX 可用于任何数据类型;SUM、AVG只能用于数字数据类型五、子…

微软将降低Visual Studio对操作系统的影响

在过去几年中,为了将Visual Studio变成Windows上的第一开发工具,而不管用户的目标平台是什么,微软作出了重大努力。最近收购Xamarin及通过大力支持开源工具来支持非Windows设备,极大地增加了它对于各类开发人员的用处。这一做法的…