精华内容
下载资源
问答
  • 主存是中央处理器能够直接存取指令和数据的存储器。能否合理而有效地使用它,在很大程度上将影响整个计算机系统的性能。 提供用户友好的界面设计模拟可变分区管理方式中根据用户的选择使用首次适应算法、最佳适应...
  • 通过redis主存复制(一主两从) 数据同步过程日志,分析Redis主从复制的工作原理,Redis允许同时开启AOF和RDB,既保证了数据安全又使得进行备份等操作十分容易。此时重新启动Redis后Redis会使用AOF文件来恢复数据,...
  • 系统采用最优适应分配算法为作业分配主存空间,而且具有紧凑技术。请编程完成以下步骤: (1)、输出此时的已分配区表和未分配区表; (2)、装入 Job3(15K),输出主存分配后的已分配区表和未分配区表; (3)、回收 ...
  • 在可变分区管理方式下,采用首次适应算法(最先适应算法)实现主存空间的分配和回收。操作系统课程设计,用C语言实现。在VC6.0上调试通过。
  • 选择一种算法在可变分区管理方式下对内存进行管理 二实验目的 掌握可变分区内存管理方式能熟练运用内存管理的各种算法对内存进行分配和回收 三实验题目 在可变分区管理方式下采用最先适应算法实现主存分配与回收 ...
  • 第四章 指令系统习题参考答案 1ASCll码是7位如果设计主存单元字长为32位指令字长为12位是否合理为什 么 解指令字长设计为12位不是很合理主存单元字长为32位一个存储单元可存放4个ASCII码余下4位可作为ASCII码的校验...
  • 链表实现:系统采用最优适应分配算法为作业分配主存空间,而且具有紧凑技术。请编程完成以下步骤::#define n 10 /*假定系统允许的最大作业 数量为n,n值为10*/ struct {int number; /*序号*/ int address; /*已...
  • 操作系统课程设计《主存空间的分配与回收》,c语言实现,附源码及报告文档
  • 广工操作系统实验 主存空间的分配与回收 带源代码源程序和报告
  • 系统采用最优适应分配算法为作业分配主存空间,而且具有紧凑技术。请编程完成以下步骤: (1). 输出此时的已分配区表和未分配区表; (2). 装入 Job3(35K),输出主存分配后的已分配区表和未分配区表; (3). 回收 ...
  • * * * * * * * * * * * * * * * * * * * * 27 (3) 最佳适应算法 什么是最佳适应算法 最佳适应算法是将输入的程序放置到主存中与它所需大小 最接近的空闲区中 程序A 18KB 空闲区队列结构 空闲区大小由小到大排序 最佳...
  • 这是dotnet / core存储库,是.NET Core(构建跨平台应用程序的开源通用开发框架)的良好起点。 .NET Core使您可以使用各种编程语言为Windows,macOS或Linux以及ARM64处理器创建应用程序。 它提供了用于云,客户端UI...
  • 什么是Cache地址映射 ...主存的容量比Cache要大的多,所以我们得采用多个主存块映射到同一个Cache行中的方法,将要访问的局部主存区域取到Cache中。映射方法有:直接映射,全相联映射,组相链映射、 ...

    (结合看过的几篇文章整理笔记)

    什么是Cache地址映射

     Cache的容量很小,它保存的内容只是主存内容的一个子集,且Cache与主存的数据交换是以块为单位的。主存每个块的大小和Cache每个块的大小相等(主存块大小=Cache块大小)。

    为了把信息放到Cache中,必须应用某种函数把主存地址定位到Cache中,这称为地址映射

    在信息按这种映射关系装入Cache后,CPU执行程序时,会将程序中的主存地址变换成Cache地址,这个变换过程叫做地址变换

    Cache的地址映射方式有:直接映射全相联映射组相联映射

    假设某台计算机主存容量为1MB,被分为2048块,每块512B;
    Cache容量为8KB,被分为16块,每块也是512B。

    下面以此为例介绍三种基本的地址映射方法。

    直接映射


    直接映射是最简单粗暴的办法:

    (块地址)mod(cache中的块数)
    

    映射规则为:Cache line index = (主存(Page)的line数)%(cache中 cache line的总数)

    一个内存块地址始终映射到一个固定的Cache 地址。就如每个人的停车位是固定分配好的,可以直接找到。

    主存中的一个块只能映射到Cache的某一特定块中去。
    下图中主存被分为了0-2047个内存块,缓存块或者说Cache line有16块。
    例如,主存的第0块、第16块、第32块、第48块、…、第2032块等128块,只能映射到Cache的第0块;
    主存的第1块、第17块、第33块、第49块、…、第2033块等128块,只能映射到Cache的第1块;
    以此类推,主存的第15块、第31块、第47块、…、第2047块等128块,只能映射到Cache的第15块中。
    映射完毕,Cache总共有0~15即16块,主存中的每128(2048/16)块,只能映射到Cache中的某一个块中。

    即映射规则为cache line index = (主存(Page)的line数)%(cache中 cache line的总数)

    主存的line数是0~2047,cache中cache line的总数是16.

    327.gif

    那么第0,16,n*16块因为mod16都为0,所以他们对应到的Cache行号都为0。

    知道了映射方法,那么如何规定主存地址呢?
    其实对于取模运算,我们只需要取低位字节就可以了。

    在十进制里面如果对16取余,那么结果定是两位数以内,并且不会大于15。

    比如说Cache有16行,16是2的4次方,那么我们就可以直接取主存块号的低四位作为Cache行号。

    Cache索引

    17对应的cache行号就是1.

    但当我们读取某一个缓存行时,我们怎么知道他是0块群的还是其他块群的呢?

    其实正如主存块号中包含了Cache行号一样,其低四位之前的高位就可以作为区分的Tag(主存标记)使用。最后一点就是,CPU读取数据只是要读取它需要的字(Word)而已,那么这个字具体是在Cache line的哪里,我们还需要一个偏移量来纪录它。

    所以直接映射的主存地址应该由三部分组成:主存子块标记,Cache子块标记,字块内地址。

    直接映射主存格式

    现在我们来自己动手做一做:假设数据在主存和Cache间的传送单位为512B,Cache大小为2^13B,主存大小为2^20B。

    因为主存大小为2^20B,且以512B为传送单位。那么2^20B=2048块 * 512B/块,主存可以划分为2048块,主存地址为20位二进制数。因为我们需要确定要取的是块中的哪个字,又512=2^9,所以需要9位作为偏移量,或者说字块内地址。 Cache可以划分出16行(2^13=16行 * 512B/行),也就是说划出4位作为行号标记,或者说Cache字块地址。剩下的7位自然就作为主存字块标记啦。

    直接映射例题

    优缺点:

    • 电路实现简单,命中时间短
    • 无需考虑替换问题
    • Cache的存储空间没有得到充分使用,命中率低

    缺点通俗理解:因为人多车位少,很可能几个人争用同一个车位,导致Cache淘汰换出频繁,需要频繁的从主存读取数据到Cache,这个代价也较高。

     

    全相联映射

    针对直接映射Cache空间利用率低的问题,我们有一种简单粗暴的办法提升空间的利用率。
    那就是主存中的任意一块都可以映射到Cache中的任意一个位置。
    有空车位你就停,随意,映射位置不在固定,停的时候简单,找车的时候需要一个一个停车位找。

    全相联映射

    全相联映射方式比较灵活,主存的各块可以映射到Cache的任一块中,Cache的利用率高,块冲突概率低,只要淘汰Cache中的某一块,即可调入主存的任一块。

    那么我们唯一要做的就是知道Cache中是对应主存中的哪一块和字块内地址就行。因为是随便映射,所以我们把直接映射中的Cache字块标记合并到主存字块标记中。

    全相联映射主存地址只有两部分:主存字块标记,字块内地址。

    优缺点:

    • 不存在冲突缺失,命中率高
    • 电路复杂,速度慢

    由于Cache比较电路的设计和实现比较困难,这种方式只适合于小容量Cache采用。

    需要存储tag来区分,tag可以理解为主存块的index,方便查找。
     

     

    组相联映射

    综合前两种方法的就是组相联映射,组相联映射实际上是直接映射和全相联映射的折中方案,组织结构如下图。(两级结构,内存块→缓存组)

    具体做法是:主存和Cache都分组,主存中一个组内的块数与Cache中的分组数相同,组间采用直接映射,组内采用全相联映射。也就是说,将Cache分成u组,每组v块,主存块存放到哪个组是固定的,至于存到该组哪一块则是灵活的。例如,主存分为256组,每组8块,Cache分为8组,每组2块。

    Cache组号=主存块号 mod Cache组数
    

     

    329.gif

    举例:

    将Cache空间划分成2^q组,每组2^s页(称为2s路相联),将主存空间分成2^m区,每个区2^q页,主存中的某区允许映射到固定组内的任意项。某区的第0页可以调入Cache0组的中的任意一页,第1页可以调入Cache1组的中的任意一页。

    现在设q=7,则Cache中有0 - 127,共128组,s = 1,每组2页(称为2路相联),每页32个字节,Cache容量为8KB。主存地址32位,m = 20,最大可分为2^20个区,每区128(2^q)页,每页32个字节。

    在这里插入图片描述

     

    (引入“区”的概念,三级结构,内存【区,组】→缓存组,原理一致)

    组相联的映象规则:

    (1) 主存和Cache按同样大小划分成块。

    (2) 主存和Cache按同样大小划分成组。

    (3) 主存容量是缓存容量的整数倍,将主存空间按缓冲区的大小分成区,主存中每一区的组数与缓存的组数相同。

    (4) 当主存的数据调入缓存时,主存与缓存的组号应相等,也就是各区中的某一块只能存入缓存的同组号的空间内,但组内各块地址之间则可以任意存放, 即从主存的组到Cache的组之间采用直接映象方式;在两个对应的组内部采用全相联映象方式。

      图2.3.6示出了组相联的映象关系, 图中缓存共分Cg个组,每组包含有Gb块; 主存是缓存的Me倍,所以共分有Me个区, 每个区有Cg组,每组有Gb块。那么, 主存地址格式中应包含4个字段:区号、区内组号、组内块号和块内地址。 而缓存中包含3个字段:组号、组内块号、块内地址。主存地址与缓存地址的转换有两部分,组地址是按直接映象方式,按地址进行访问,而块地址是采用全相联方式,按内容访问。组相联的地址转换部件也是采用相关存储器实现,见图2.3.7。

    二级结构和三级结构原理一致。

    简单举例理解如下:缓存8K,一个缓存块大小521B,分16块,分8组,一组2块。内存1MB,一个内存块大小521B,分2048块。

    二级结构:主存和Cache都分组,主存中一个组内的块数与Cache中的分组数相同。

    则,主存2048块以8块为一组,分为256个组。256个组每个组的第一块都是映射到缓存第0组,即一组缓存(2块)对应256个内存块。

    三级结构:(1) 主存和Cache按同样大小划分成块。(2) 主存和Cache按同样大小划分成组。(3) 主存容量是缓存容量的整数倍,将主存空间按缓冲区的大小分成区,主存中每一区的组数与缓存的组数相同。

    缓存共分8个组,每组包含有2块; 主存是缓存的(1MB/8K=128)倍,所以共分有128个区, 每个区有8组,每组有2块。

    128个区每一个区的第0组(2块内存块)都映射到缓存的第0组,内存块总数128*2=256块,依旧是一组缓存(2块)对应256个内存块。

    两个结构表述不同,但原理是一致的。

     

    那么问题来了怎么确定Cache中的字块是对应主存的那一块呢?首先我们仍需要字块内地址,需要区分组号,那么剩下的地址就可以作为主存字块标记使用。

    实例分析1:

    容量为64块的Cache,采用组相联方式映像,字块大小为128字,每4块为一组。若主存容量为4096块,且以字编址,那么主存地址该如何划分?

    因为4096=219,所以主存地址应该为19位,Cache总共有16组,所以需要4位确定组号。又字块大小为128字,128=2^7,所有字块内地址为7位,剩下的19-7-4=8位作为主存字块标记

    组相联例题

    实例分析2:

    1.容量为64块的Cache采用组相联方式映像,字块大小为128字节,每4块为一组,若主容量为4096块,且以字编址,那么主存地址为(19)位,主存区号为(6)位。

    解:组相联的地址构成为:区号+组号+块号+块内地址。

    主存的每个分区/组大小与整个Cache大小相等,故此主存需要分的区数为:4096/64=64,因为26=64,因此需要6位来表示区号。

    每4块为一组,故共有组数 64/4 = 16 ,因为24=16,因此需要4位表示组号。每组4块,故表示块号需要2位。

    块内地址共128字节,27=128,所以块内地需要7位表示。所以:主存地址的位数=6+4+2+7 = 19

    主存区号的位数=6

    以上两个实例问题相似,但解答不同,我也想不通了,版本不同吧。

    优缺点:

    • 电路较简单,速度较快,命中率较高,属于比较理想的方式

          常采用的组相联结构Cache,每组内有2、4、8、16块,称为2路、4路、8路、16路组相联Cache。组相联结构Cache是前两种方法的折中方案,适度兼顾二者的优点,尽量避免二者的缺点,因而得到普遍采用。
     

     

     

     

    展开全文
  • 操作系统课程实验,主存空间的分配和回收,代码加报告文档
  •   可变分区方式是按作业需要的主存空间大小来分割分区的。当要装入一个作业时,根据作业需要的主存量查看是否有足够的空闲空间,若有,则按需要量分割一个分区分配给该作业;若无,则作业不能装入。随着作业的装入...

    一、算法基本思想

      可变分区方式是按作业需要的主存空间大小来分割分区的。当要装入一个作业时,根据作业需要的主存量查看是否有足够的空闲空间,若有,则按需要量分割一个分区分配给该作业;若无,则作业不能装入。随着作业的装入、撤离,主存空间被分成许多个分区,有的分区被作业占用,而有的分区是空闲的。为了说明哪些区是空闲的,可以用来装入新作业,必须要有一张空闲区说明表。当有一个新作业要求装入主存时,必须查空闲区说明表,从中找出一个足够大的空闲区。有时找到的空闲区可能大于作业需要量,这时应把原来的空闲区变成两部分:一部分分给作业占用;另一部分又成为一个较小的空闲区。为了尽量减少由于分割造成的空闲区,而尽量保存高地址部分有较大的连续空闲区域,以利于大型作业的装入。为此,在空闲区说明表中,把每个空闲区按其地址顺序登记,即每个后继的空闲区其起始地址总是比前者大。为了方便查找还可使表格“紧缩”,总是让“空表目”栏集中在表格的后部。采用最先适应算法(顺序分配算法)分配主存空间。按照作业的需要量,查空闲区说明表,顺序查看登记栏,找到第一个能满足要求的空闲区。当空闲区大于需要量时,一部分用来装入作业,另一部分仍为空闲区登记在空闲区说明表中。由于本实验是模拟主存的分配,所以把主存区分配给作业后并不实际启动装入程序装入作业,而用输出“分配情况”来代替。

    分配的流程图:
    在这里插入图片描述
    当一个作业执行结束撤离时,作业所占的区域应该 归还,归还的区域如果与其它空闲区相邻,则应合成一个较 大的空闲区,登记在空闲区说明表中。例如,在提示(1) 中列举的情况下,如果作业2撤离,归还所占主存区域时, 应与上、下相邻的空闲区一起合成一个大的空闲区登记在空闲区说明表中。归还时的流程图如下:
    在这里插入图片描述

    二、程序所用的数据结构和符号说明

    函数FIRST_FIT()提供功能选择页面,函数init()初始化空闲区信息,在该步中已经装入三个作业,函数input()装入作业分配内存,函数finish()撤销作业回收内存,函数merge()实现相邻空闲区合并操作,函数sort()让空闲区按照起始地址从小到大排序,output1和output2实现相关输出展示。

    三、具体实现

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <iomanip>
    
    #define n 100					// 最大空闲区个数
    using namespace std;
    
    int p_num = 4;					// 作业个数
    int num = 2;					// 空闲区个数
    
    struct
    {
    	char name[20];
    	int address;
    	int length;
    	int flag;
    } free_table[n], work_table[n], temp;
    
    void sort()		// 空闲区按起始地址从小到大排序
    {
    	int i;
    	for (i = 0; i < num - 1; i++)
    		for (int j = 0; j < num - i - 1; j++)
    			if (free_table[j].address > free_table[j + 1].address)
    			{
    				temp = free_table[j];
    				free_table[j] = free_table[j + 1];
    				free_table[j + 1] = temp;
    			}
    
    	for (i = 0; i < p_num - 1; i++)
    		for (int j = 0; j < p_num - i - 1; j++)
    			if (work_table[j].address > work_table[j + 1].address)
    			{
    				temp = work_table[j];
    				work_table[j] = work_table[j + 1];
    				work_table[j + 1] = temp;
    			}
    }
    
    
    void merge()		// 扫描空闲区若前后有相邻空闲区则合并
    {
    	for (int i = 0; i < num-1; i++)
    	{
    		if (free_table[i].address + free_table[i].length == free_table[i+1].address)
    		{
    			if(!free_table[i].flag && !free_table[i+1].flag)
    			{
    				free_table[i].length += free_table[i+1].length;
    				for (int j = i+1; j < num-1; j++)
    						free_table[j] = free_table[j + 1];
    				i--;
    				num--;
    			}
    		}
    	}
    }
    
    
    void output1()		// 输出空闲区表信息
    {
    	cout << "空闲区表:" << endl << "    起始地址" << "\t" << "长度" << "\t"<<"状态" <<endl;
    	for (int i = 0; i < num; i++)
    		cout  << "\t" << free_table[i].address << "\t" << free_table[i].length << "\t" <<free_table[i].flag << endl;
    		cout << endl ;
    }
    
    void output2()		// 输出已分配区表信息
    {
    	cout << "已分配区表:" << endl << "    起始地址" <<"\t" << "长度" <<"\t" <<"状态" << "\t" <<"占用作业" <<endl;
    	for (int i = 0; i < p_num; i++)
    		cout << "\t" <<work_table[i].address << "\t" << work_table[i].length << "\t" << work_table[i].flag <<"\t" <<work_table[i].name << endl;
    		cout << endl;
    }
    
    // 初始化空闲区信息
    void init()
    {
    	cout <<"------------最先适应算法------------" << endl ;
    
        work_table[0].address =0;
        work_table[0].length =10;
        work_table[0].flag = 1 ;
        strcpy(work_table[0].name, "操作系统");
    
    	work_table[1].address = 10;
        work_table[1].length= 4;
    	work_table[1].flag = 1;
    	strcpy(work_table[1].name, "1");
    
    	work_table[2].address = 32;
        work_table[2].length= 96;
    	work_table[2].flag = 1;
    	strcpy(work_table[2].name, "2");
    
    	work_table[3].address = 14;
        work_table[3].length= 12;
    	work_table[3].flag = 1;
    	strcpy(work_table[3].name, "3");
    
    	free_table[0].address = 26;
    	free_table[0].length =6;
    	free_table[0].flag = 0;
    
    	free_table[1].address = 128;
    	free_table[1].length =896;
    	free_table[1].flag = 0;
    
    	sort();
    	merge();
    	cout << endl ;
        sort();
    
    	output1();
    	output2();
    }
    
    // 装入作业,分配内存
    void input()
    {
    	int i, length;
    	char name[20];
    	cout << "输入作业序号: ";
    	gets(name);
    	cout << "输入作业大小: ";
    	cin >> length;
    	fflush(stdin);
    
    	for (i = 0; i < num; i++)
    	{
    		if(!free_table[i].flag)
    		{
    			if (length < free_table[i].length)
    			{
    				work_table[p_num].address = free_table[i].address;
    				free_table[i].length = free_table[i].length - length;
    				free_table[i].address = free_table[i].address + length;
    				strcpy(work_table[p_num].name, name);
    				work_table[p_num].flag = 1;
    				work_table[p_num].length = length;
    				p_num++;
    				break;
    			}
    			else if (length == free_table[i].length)
    			{
    				strcpy(work_table[p_num].name, name);
    				work_table[p_num].flag = 1;
    				work_table[p_num].address = free_table[i].address;
    				work_table[p_num].length = free_table[i].length;
    				p_num++;
    				for(int j=i; j<num; j++)
    				{
    					free_table[j]=free_table[j+1];
    				}
    				num--;
    				break;
    			}
    		}
    	}
    	if (i == num)
    	{
    		cout << endl << "无合适空闲区,不能为作业分配内存!" << endl;
    		return;
    	}
    	sort();
    	output1();
    	output2();
    }
    
    // 撤消作业,回收内存
    void finish()
    {
    	char name[20];
    	int i;
    	cout <<"输入作业序号:";
    	gets(name);
    	fflush(stdin);
    	bool flag = 0;
    	for (i = 0; i < p_num; i++)
    	{
    		if (!strcmp(name, work_table[i].name))
    		{
    			free_table[num] = work_table[i];
    			free_table[num].flag = 0;
    			num++;
    
    			sort();
    			merge();
    
    			for(int j = i; j < p_num; j++)
    				work_table[j] = work_table[j+1];
    			p_num--;
    			flag = 1;
    			break;
    		}
    	}
    	if (!flag)
    		cout << endl <<"没有此作业,重新输入!";
    	output1();
    	output2();
    }
    
    void FIRST_FIT()
    {
    	init();
    	while (1)
    	{
    		int c;
    		cout << "1.装入作业" << endl << "2.撤销作业" << endl << "3.退出" <<"请输入你的选择:";
    		cin >> c;
    		cout <<endl;
    		fflush(stdin);
    		if (c == 1)
    			input();
    		else if (c == 2)
    			finish();
            else break;
    	}
    }
    
    int main(void)
    {
    	FIRST_FIT();
    	return 0;
    }
    

    四、实验结果

    假设主存中已装入三个作业,且形成两个空闲区,确定空闲区说明表的初值。现有一个需要主存量为6K的作业4申请装入主存;然后作业3撤离;再作业2撤离。请你为它们进行主存分配和回收,把空闲区说明表的初值以及每次分配或回收后的变化显示出来或打印出来。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • Cache-主存地址映射

    2021-05-31 00:11:39
    Cache-主存地址映射 这几天十分懒惰,都没有复习计组,现在勉强把第四章看完了,最后一个内容Cache-主存地址映射一开始看不懂,现在终于差不多懂了,再把做题的步骤写下来供下次参考 题目一 假设主存容量为512K,...

    Cache-主存地址映射

    这几天十分懒惰,都没有复习计组,现在勉强把第四章看完了,最后一个内容Cache-主存地址映射一开始看不懂,现在终于差不多懂了,再把做题的步骤写下来供下次参考

    题目一

    假设主存容量为512K,Cache容量为4KB,每个子块为16个字,每个字32位。

    (1)Cache地址有多少位?可容纳多少块?

    题目没有说是按字访存,所以默认就是按照字节来访存。所以Cache的地址有多少位呢,我们就先看看它有多少个字节。

    Cache的容量是4KB,所以一共有4K个字节。所以Cache地址的位数就是 l o g 2 4 K log_2{4K} log24K=12。

    可以容纳多少块呢?我们看看每块里面包含了什么。

    每个字块有16个字,每个字是32位。这里一定要区分字和字节的概念。一个字的基本单位是字节,就像英语中一个音标的基本单位是音节。在这道题中的字是32位,也就是4个字节,又因为子块中有16个字。所以一个字块中有64个字节。

    Cache的容量是4K个字节,每个字块有64分个字节,所以一除就得到了可容纳字块的块数: 2 12 / 2 6 = 2 6 = 64 2^{12}/2^{6}=2^{6}=64 212/26=26=64

    (2)主存地址有多少位?可容纳多少块?

    和(1)类似。答案为19位和8192块。

    (3)画出直接映射方式下主存地址字段中各段的位数。

    这里有一个预备知识,直接映射方式下主存地址被划分为三段。

    分别是主存字块标记,cache字块地址,字块内地址。我们需要求出这三种地址的度

    字块内地址怎么求呢?得看你是用字节来访存还是用字来访存。如果是用字节来访存得话,这个字块内地址的长度就得用字节个个数来确定。比如这道题是用字节来访存的,一个字块内一共有64个字节,所以得字块内地址地址得长度就应该是6( l o g 2 64 = 6 log_{2}{64}=6 log264=6) 如果是用字来访存得话,就是用字得长度来确定地址得长度。

    那这个cache字块地址得长度怎么求呢?其实就是求有多少个字块。因为这种长度其实就是对应了数量。 2 地 址 长 度 = 数 量 2^{地址长度}=数量 2=

    那cache有多少个字块呢?之前已经求过了,是64块,所以长度是 6 6 6

    此外我们还可以这样来求cache字块地址字长,我们知道直接映射方式,主存得一部分和cache是一一对应的,所以cache的地址在主存地址中完全体现的,又在第一题里,cache的地址位数是12位,我们之前还求除了cache字段内地址的长度是6,所以 12 − 6 = 6 12-6=6 126=6就得到了cache字块地址的长度。

    最后一个主存字块标记的长度就是主存地址总位数减去cache字块地址长度再减去字块内地址长度 19 − 6 − 6 = 7 19-6-6=7 1966=7

    题目二

    假设主存容量为512K*16位,Cache容量位4096*16位,块长位4个16位的字,访存地址为字地址。

    (1)在直接映射方式下,设计主存的地址格式

    我们观察到这道题和题目一不同,它的访存地址的字地址。

    我们来看看具体的差别,当然,对于直接映射的方式,主存的地址还是由三种地址组成,分别是主存字块标记、cache字块地址、字块内地址。

    字块内地址我们再上一题是把一个字块内有多少字节求出来然后求得长度,但是现在是按字访存,所以我们得求出来一个字块中有多少个字。

    题目中很明显得写出来了,块长为4个16位的字,很明显那一个字块中一共就有4个字,所以长度为2。

    然后cache字块地址的长度我们就来看看字块的个数。现在我们知道一个字块中有4个字,所以我们只要求出cache中总共有多少个字。然后利用总字数/每个子块中字的个数就可以求出子块数。

    我们发现这道题中的容量都是用乘法来表示的,而不是用B来表示,其实这就是用字地址访存的预兆,这样表示也可方便计算。

    比如我们通过cache容量位 4096 ∗ 16 4096*16 409616位就可以得到总字数。因为每个字是16位,所以很显然,总共的字数就是4096个。再除以每个子块中的字数,得到 4096 / 4 = 1024 4096/4=1024 4096/4=1024块,所以cache子块地址的长度是10位。

    最后的主存子块标记的长度,我们得求出主存地址得总位数,然后减去cache字块地址长度10和字块内地址长度2。

    因为主存容量位512K,所以它得主存地址长度是19位,故主存字块标记得长度是19-10-2=7

    (2)再全相联映射方式下,设计主存得地址格式。

    全相联映射,主存地址分为两部分,分别是主存字块标记和字块内地址。

    由(1)得知,字块内地址得长度是2,又主存地址总长度是19,所以很容易求出主存字块标记为17。

    所以全相联映射得地址格式求起来是最简单得。

    (3)在二路相联映射方式下,设计主存得地址格式。

    组相联映射方式得主存地址也是三部分,分别是主存字块标记、组地址以及字块内地址长度。

    我们发现三种映射方式,主存地址中都有主存字块标记字块内地址长度

    字块内地址长度和之前保持一致,还是2。

    求组地址长度,就得求出一共有多少组。因为是2路相连,就是把把所有得字块进行划分组,使得一组中有两个字块。我们知道字块得数量是1024块,又因为一组中有两块,那么很容易知道一共有512组。那么组地址得长度就是8。

    减一下得到主存字块标记长度为19-9-2=8

    (3)若主存容量为512K*32位,块长不变,在四路组相联映射方式下, 设计主存的地址格式。

    块长不变,所以块内地址长度还是2。

    然后改变主存容量可以改写为 1024 K ∗ 16 位 1024K*16位 1024K16。但是主存容量的改变影响的只是主存地址的总长度,和组地址长度没有关系。

    求组地址的长度我们还是得求字块被划分出了多少组,cache中得总块数是不变得,但是从2路相联映射变成了4路相联映射,所以每一组组中从2个字块变成了4个字块,所以最后得组就是除以2,变成了256组,长度为8。这里我们还可以总结出一个结论就是,除以2其实长度就减,之前得组数是512,9位,现在256,8位,下次看到类似题目,直接长度减1即可,不用求出具体得组数。

    主存字块标记就是主存地址长度减去组地址长度再减去字块内地址长度。我们要注意主存容量翻倍了,所以总长度+1,变成了20。

    所以主存字块标记长度20-8-2=10

    总结

    1. 这类题目一定要看清楚是按字访存还是按字节访存(不说就是按字节访存)

    2. 记清楚三种映射方式地址得构成

    展开全文
  • 今天,我们来聊聊一个让程序员很头疼的话题:计算机中的主存是如何进行编址和计算的? 文章已收录到: https://github.com/sunshinelyz/technology-binghe https://gitee.com/binghe001/technology-binghe 主存编址...

    写在前面

    很多小伙伴认为程序员就是写写代码,不需要了解计算机底层的知识和原理。其实,这种观点是错误的。如果你想突破程序员的职业发展瓶颈,计算机硬件、操作系统原理、编译原理等是一定要掌握的知识。而【冰河技术】微信公众号的【程序员进阶系列】专题就是要系统的向大家分享程序员进阶需要掌握的各项知识技能。今天,我们来聊聊一个让程序员很头疼的话题:计算机中的主存是如何进行编址和计算的?

    文章已收录到:

    https://github.com/sunshinelyz/technology-binghe

    https://gitee.com/binghe001/technology-binghe

    主存编址与计算

    这里,小伙伴们首先要区分两个概念,一个是编址,一个是寻址。

    编址: 存储器是由一个个存储单元构成的,为了对存储器进行有效的管理,就需要对各个存储单元编上号,即给每个单元赋予一个地址码,这叫编址。经编址后,存储器在逻辑上便形成一个线性地址空间。

    寻址: 存取数据时,必须先给出地址码,再由硬件电路译码找到数据所在地址,这叫寻址。

    编址可以分为两种:按字编址和按字节编址
    在这里插入图片描述

    • 按字编址:存储体的存储单元是字存储单元,即最小寻址单位是一个字。
    • 按字节编址:存储体的存储单元是字节存储单元,即最小寻址单位是一个字节。

    对于主存编址中最常见的计算形式为:根据存储器所要求的容量和选定的存储芯片的容量,就可以计算出所需要的芯片的数量。公式如下所示。

    总片数 = 总容量 / 每片的容量
    

    这里,给小伙伴们举一个例子:若内存地址区间为4000H ~ 43FFH,每个存储单元可存储16位二进制数,该内存区域使用4片存储器芯片构成,则构成该内存所用的存储器芯片的容量是多少?

    解题思路也比较简单,我们一起来看看如何解题:

    (1)首先,我们来求解4000H ~ 43FFH地址空间的总容量,使用终止地址-起始地址+1即可得到总容量,也就是43FFH - 4000H + 1 = 43FFH + 1 - 4000H = 4400H - 4000H = 400H。

    注意:在计算机中,以H结尾的数字是十六进制,逢16进1,而F在十六进制中表示15,所以,43FFH + 1 = 4400H。

    所以,4000H ~ 43FFH地址空间的总容量为400H。

    (2)接下来,我们要把400H转换成二进制,对于十六进制数转换成二进制数来说,每一位十六进制数对应着四位的二进制数,我们可以把400H拆分成4、0、0三部分,4转换成二进制数就表示0100,十六进制的0转换成二进制为0000。所以,400H转换成二进制的结果为:0100 0000 0000。

    0100 0000 0000也就是2的10次方,即为210

    (3)题目中说的每个存储单元可存储16位二进制数,所有总共可以存储的二进制数就是:210 * 16。

    (4)该区域使用4片存储器芯片构成,所以,存储芯片的容量为:210 * 16 / 4 = 210 * 4 = 212,最终的结果单位为bit。

    总线

    一条总线同一时刻只允许一个设备发送数据,但允许多个设备接收数据。

    总线的分类

    总线可以分为数据总线、地址总线和控制总线。
    在这里插入图片描述

    • 数据总线(Data Bus):在CPU和RAM之间来回传送需要处理或是需要存储的数据。
    • 地址总线(Address Bus):用来指定在RAM(Random Access Memory)之中存储的数据的地址。
    • 控制总线(Control Bus):将微处理器控制单元(Control Unit)的信号传送到周边设备,一般常见的为USB Bus和1394 Bus。

    串联系统与并联系统

    这里,先给小伙伴们简单介绍下什么是串联系统,什么是并联系统。

    串联系统

    串联系统是组成系统的所有单元中任一单元失效就会导致整个系统失效的系统。把用电器各元件逐个顺次连接起来,接入电路就组成了串联电路。我们常见的装饰用的"满天星"小彩灯,常常就是串联的。串联电路有以下一些特点:⑴电路连接特点:串联的整个电路是一个回路,各用电器依次相连,没有"分支点"。⑵用电器工作特点:各用电器相互影响,电路中一个用电器不工作,其余的用电器就无法工作。⑶开关控制特点:串联电路中的开关控制整个电路,开关位置变了,对电路的控制作用没有影响。即串联电路中开关的控制作用与其在电路中的位置无关。

    注:以上对于串联系统的描述来源于网络。

    接下来,我们来看一个关于串联系统的图形表示,这里我们假设串联系统中每个部分的可靠度依次为R1,R2,…Rn,如下所示。

    在这里插入图片描述

    则整个系统的可靠度为:R = R1 * R2 * … * Rn。

    并联系统

    并联系统指的是组成系统的所有单元都失效时才失效的系统。把电路中的元件并列地接到电路中的两点间,电路中的电流分为几个分支,分别流经几个元件的连接方式叫并联。并联电路是使在构成并联的电路元件间电流有一条以上的相互独立通路,为电路组成二种基本的方式之一。例如,一个包含两个电灯泡和一个9 V电池的简单电路。若两个电灯泡分别由两组导线分开地连接到电池,则两灯泡为并联。

    即若干二端电路元件共同跨接在一对节点之间的连接方式。这样连成的总体称为并联组合。其特点是:①组合中的元件具有相同的电压;②流入组合端点的电流等于流过几个元件的电流之和;③线性时不变电阻元件并联时,并联组合等效于一个电阻元件,其电导等于各并联电阻的电导之和,称为并联组合的等效电导,其倒数称为等效电阻

    注:以上对于并联系统的描述来源于网络。

    接下来,我们来看一个关于并联系统的图形表示,这里我们假设并联系统中每个部分的可靠度依次为R1,R2,…Rn,如下所示。
    在这里插入图片描述

    则整个并联系统的可靠度R = 1 - (1 - R1) * (1 - R2) * … * (1-Rn)。

    混合型系统

    混合型系统就是既有串联系统,又有并联系统的系统,这里,我们也使用一个图形进行表示,如下所示。

    在这里插入图片描述

    所以,上图并联系统的可靠度为:R * (1 - (1 - R) 3) * (1 - (1 - R) 2)

    好了,今天就到这儿吧,我是冰河,大家有啥问题可以在下方留言,也可以加我微信:sun_shine_lyz,我拉你进群,一起交流技术,一起进阶,一起牛逼~~

    展开全文
  • 采用最先适应法、最佳适应法、最坏适应法分配主存空间 内容详细 二、实验内容 1 本实验是模拟操作系统的主存分配,运用可变分区的存储管理算法设计主存分配和回收程序,并不实际启动装入作业。 2 采用最先适应法、...
  • 主存与cache间的地址映射

    千次阅读 2020-12-22 22:38:35
    ①cache与主存之间的数据交换是以“块”为单位进行的。一个“块”中包含若干个“字”,字长由实际情况确定。      习惯上,cache中的“块”称“行”,主存中称“块”。cache的“行”与主存的“块”...
  • cache-主存的三种映射方式

    千次阅读 2021-05-04 10:00:23
    cache-主存的三种映射方式2.1 全相联映射2.2 直接映射方式2.3 组相联映射方式3. 三种映射方式例题 1. 基本概念 1. 存储系统的体系结构 图片摘自这篇博客:图片来源 2. cache在存储系统中的位置 cache(缓存)...
  • 一、主存管理概述 内存作为系统的重要资源,是系统运行的“瓶颈”。 存储管理指存储器资源(主要指内存并涉及外存)的管理。 存储器的多级存储结构 存储体系是OS在存储技术和CPU寻址技术许可范围内组织合理的存储...
  • 操作系统课程设计——主存空间的分配与回收
  •   分页式存储器把主存分成大小相等的若干块,作业的信息也按块的大小分页,作业装入主存时可把作业的信息按页分散存放在主存的空闲块中,为了说明主存中哪些块已经被占用,哪些块是尚未分配的空闲块,可用一张位示...
  • 主存容量扩展

    千次阅读 2020-10-20 13:53:44
    当存储芯片的位与CPU的位数不一致时,可以采取位扩展的方式 假设我们买了一个CPU,它有15...如下面两幅图所示,就是连接的模型图,也就是主存容量的位扩展位,8K8位,也就是主存容量是8KB。 当CPU的容量不能满足时
  • 用C/C++语言模式Linux操作系统主存的分配与回收,希望采纳!
  • 大三操作系统要求的课程设计报告,比较完整的主存分配 和回收,采用了要求的三种算法来实现的
  • 主存的分配和回收的实现是与主存储器的管理方式有关的。所谓分配,就是解决多道作业或多进程如何共享主存空间的问题。所谓回收,就是当作业运行完成时将作业或进程所占的主存空间归还给系统。
  • 解释概念:主存、辅存、Cache、RAM
  • 存储器之主存--Cache--辅存大全

    千次阅读 2020-03-23 22:45:40
    目录 概述 存储器分类 存储器的层次结构 主存储器 概述: 半导体芯片简介 随机存取存储器(RAM)...主存—Cache的地址映射 写操作 Pentium的Cache 辅助存储器 ​ 概述 存储器分类 按存储介质分类: ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 65,577
精华内容 26,230
关键字:

主存