操作系统实验报告三 存储管理 任务二

实验三 存储管理

任务二

一、实验名称

       存储管理之设计实验

二、实验目的

编写和调试内存管理调度模拟程序,掌握存储管理算法,理解存储管理中地址转换过程。

三、实验过程

1、设计一个固定式分区分配的存储管理方案,并模拟实现分区的分配和回收过程。
假定每个作业都是批处理作业,且不允许动态申请内存。为实现分区的分配和回收,可设定一个分区表,按照表中的有关信息进行分配,并根据分区的分配和回收情况修改该表。
要求∶
1)描述模型、定义数据结构。
①模型:预先将内存空间固定地划分为若干个空闲分区,这样每个分区的大小就确定了,分配内存时作业大小将某一个满足条件的分区直接分配,整个分配和回收过程分区的大小和个数不改变s。
②数据结构
已分配区表

struct
{
    float address;  //起始地址
    float length;  //长度
    int flag;   //登记栏标志
} used_table[n]; 

空闲区表

struct
{
    float address;  //起始地址
    float length;  //长度
    int flag;   //登记栏标志
} free_table[m]; 

2)写代码实现并运行调试。
3)给出运行的数据和结果 。
见下图:
初始设置:
在这里插入图片描述

分配内存:
在这里插入图片描述

回收内存并为新的作业分配内存:
在这里插入图片描述
2、设计一个可变式分区分配的存储管理方案并定义数据结构、写代码运行并调试。
要求∶
1)模拟实现分区的分配和回收过程 。
2)分区的管理算法可选择∶首次适应算法、循环首次适应算法和最佳适应算法三种之一,或者自行定义。

这里我采用的是首次适应算法。
首先所谓可变式分区分配是指根据作业的实际需要,动态地为之分配内存。
而首次适应算法,要求空闲分区链以地址递增的次序链接,在分配内存时,从链首开始顺序查找,直到找到一个大小能满足要求的空闲分区为止,然后再按照作业的大小,从该分区中划出一块内存空间分给请求者,余下的空闲分区仍停留在空闲链中。
当回收内存时,系统根据回收区的首址,从空闲区链表中找到相应的插入点,这时若
回收区与插入点的前一个空闲分区F1相邻接,则将两个分区合并;若回收区与插入点的后一个空闲分区F2相邻接,则将两个分区合并;若回收区与插入点的前,后两个空闲分区相邻接,则将三个分区合并;若回收区既不与F1相邻接,又不与F2相邻接,则应为回收区单独建立一个新表项。
为多个作业申请内存:
在这里插入图片描述
回收并分配新的内存:
在这里插入图片描述
3、设计并调试一个段页式存储管理的地址转换的模拟程序。
要求∶
1)设计段表、页表。
段表

for(i=0; i < n; i++)
  {
      parag[i].length=i+4;
      parag[i].state=1;
      parag[i].PTID=d;
      d+=parag[i].length;
  }

页表

for(i = 0; i < d; i++)
  {
      page[i].state=1;
      page[i].MMID=(i+7)%d;
  }
}

结果如下图:
在这里插入图片描述
变换过程如下:
①根据段号为2和段内页号为 3,查询段表和页表信息,得到物理块号 19 ;
②由物理块号 19 和块内偏移 428 ,计算19*1024+428=19884即得物理地址 31148 。

四、实验总结

1、对固定分区和可变分区的理解与辨析
固定分区是将内存划分为一块块固定大小的分区,顺序查找可以放下作业的分区,一旦被某个作业占用,即使该分区还有空闲区域也不能使用。
2、…

五、代码

1、固定式分区分配的存储管理
#include<stdio.h>
#include<stdlib.h>

void Allocate(int id, int size);
void Release(int id);
void insert();//输入
void del();
void run();
void start();
void display();
void table(); 

struct ProcessInfo{
	int id;  
	int size; 
};


struct PartitionInfo{
	int id; 
	int size; 
	int beginAddress; 
	char status;   
};
struct ProcessInfo process[5]; 
struct PartitionInfo partition[5];
int a[5][2];   

void Allocate(int id, int size){
	int i;
	int j;
	for(i=0;i<5; i++){   
		if(partition[i].status=='T'){ 
			if(partition[i].size>=size){ 
			partition[i].status='F';   
			for(j=0;j<5;j++){
				if(a[j][0]==0){//更新分区表
					a[j][0]=id;
					a[j][1]= partition[i].id;
					printf("插入成功!!\n");
					return;
				}
			}
		}
	}
	}
	printf("分配失败!!! 没有可用的内存分区!!!\n");
	return ;

}

void Release(int id){
	int i;
	int j;
	for(i=0;i<5;i++){  
		if(a[i][0]==id) 
		{
			for(j=0;j<5;j++)
			{
				if(a[i][1]==partition[j].id){
					partition[j].status='T';
				}
			}
			for(j=i ;j<5-1;j++){	
			a[j][0]=a[j+1][0];
			a[j][1]=a[j+1][1];
			}


		}
	}
}

void insert(){
	int id;
	int size;
    int i;
	printf("请输入进程号:");
	scanf("%d",&id);
	for(i=0;i<5;i++){
		if(a[i][0]==id){  
			printf("分配失败!!!  进程ID相同!!!\n");
			return ;
		}
	}
	printf("请输入进程所需的内存空间大小:");
	scanf("%d",&size);
	Allocate(id,size);
	return;
}

void del(){
	int id;
	printf("请输入要退出的进程号:");
	scanf("%d",&id);
	Release(id);
	return;
}

void start(){
	int i,j;
	partition[0].beginAddress=0;
	for(i=0;i<5;i++){
		a[i][0]=0;
		a[i][1]=0;
	}
	for(j=0;j<5;j++){
		partition[j].id=j+1;
		printf("输入地%d个分区大小:",j+1);
		scanf("%d",&partition[j].size);
		partition[j].beginAddress+=partition[j-1].beginAddress+partition[j-1].size;
		partition[j].status='T';
	}
}
void dispaly(){
	int i;
	printf("分区id\t分区大小\t分区首地址\t分区状态(T表示可用,F表示不可用)\n");
	for(i=0;i<5;i++){
	printf("%d\t%d	\t%d	\t%c\n",partition[i].id,partition[i].size,partition[i].beginAddress,partition[i].status);
	}
}

void table(){
	int i;
	printf("进程id  内存分区id\n");
	for(i=0;i<5;i++){
		printf("%d\t%d\n",a[i][0],a[i][1]);

	}
}

void run(){
	int flag=1;
	int choose;
	start();

	while(flag){
	dispaly();
	table();
		printf("选择你要进行的操作:1: 分配一个进程 2:释放一个进程   3:退出\n");
		scanf("%d",&choose);
		switch(choose){
		case 1: insert();
			break;
		case 2:  del();
			break;
		case 3:  flag=0;
			break;
		}
	}
}

int main(){
	 run();
}
2、可变式分区分配的存储管理
#include <stdio.h>
#include <stdlib.h>
enum isAllocated{yes, no};		
typedef struct Node {
	int id;					
	int start;				
	int length;				
	enum isAllocated isallocated;	
	struct Node* next;			
	struct Node* prev;		
}Node;

Node* head;					

void printMenu() {

	printf("\n1. 申请内存\n");
	printf("2. 释放内存\n");
	printf("0. 退出\n");
	printf("请选择:");
}

void init(int capacity) {
	Node* p = (Node*)malloc(sizeof(Node));		
	p->id = -1;
	p->start = 0;
	p->length = capacity;
	p->isallocated = no;
	p->prev = NULL;
	p->next = NULL;

	head = p;
}

// 打印空闲分区
void printSpare() {
	Node* p = head;
	printf("空闲分区如下:\n起始地址\t长度\n---------------------\n");
	while (p != NULL) {
		if (p->isallocated == no) {
			printf("%d\t\t%d\n", p->start, p->length);
		}
		p = p->next;
	}
}

// 申请内存
void getMemory() {
	int id, size;
	Node* p;
	printf("请输入作业号和要申请的内存大小:");
	scanf("%d%d", &id, &size);

	p = head;
	while (p != NULL) {
		// 当找到一块长度大于所需空间的空闲分区时
		if (p->isallocated == no && p->length > size) {
			// 首先新建一个结点
			Node* newNode = (Node*)malloc(sizeof(Node));
			newNode->id = id;
			newNode->length = size;		
			newNode->isallocated = yes;
			newNode->start = p->start;		
			p->start += size;				
			p->length -= size;			
	
			if (p != head) {
				newNode->prev = p->prev;
				p->prev->next = newNode;
				newNode->next = p;
				p->prev = newNode;
			}
			else {
				newNode->prev = NULL;
				newNode->next = p;
				p->prev = newNode;
				head = newNode;
			}
			break;
		}	
		else if (p->isallocated == no && p->length == size) {
			p->id = id;			
			p->isallocated = yes;
			break;
		}
		p = p->next;
	}

	if (p == NULL) {
		printf("没有足够的内存可以分配了!\n");
	}
}

void returnMemory() {
	int id;
	Node* p;
	printf("请输入要释放内存的作业号:");
	scanf("%d", &id);

	p = head;
	while (p != NULL) {
		// 根据作业号查找要释放的作业
		if (p->id == id) {
			p->id = -1;
			p->isallocated = no;
			// 如果此作业前面还有空闲分区,则与之合并
			if (p->prev != NULL && p->prev->isallocated == no) {
				p->start = p->prev->start;
				p->length += p->prev->length;
				p->prev = p->prev->prev;
				p->prev->next = p;
			}
			// 如果此作业后面还有空闲分区,则与之合并
			if (p->next != NULL && p->next->isallocated == no) {
				p->length += p->next->length;
				p->next = p->next->next;
				p->next->prev = p;
			}
			break;
		}
		p = p->next;
	}

	if (p == NULL) {
		printf("您输入的作业号不存在!\n");
	}
}

int main() {
	int option;			
	int capacity;		

	printf("请先输入内存的容量:");
	scanf("%d", &capacity);
	init(capacity);		
	printSpare();

	while (1) {
		printMenu();		
		scanf("%d", &option);	
		switch (option)			
		{
		case 1:
			getMemory();		
			break;
		case 2:
			returnMemory();		
			break;
		case 0:					// 退出
			return 0;
		default:
			break;
		}
		printSpare();		// 打印空闲分区
	}
	return 0;
}
3、段页式存储管理的地址转换的模拟程序
#include <stdio.h>
#include <stdlib.h>

#define n 4 
//段表
struct Parag
{
    int state;
    int length;
    int PTID;
}parag[4];


struct Page
{
    int state;
    int MMID;
}page[100];

void print(int did, int ptid)
{
    int i;
    printf("段表的信息:\n");
    printf("段号\t|状态\t|段表大小\t|页表始址|\n");
    for(i=0; i < n; i++)
       printf("%d\t|%d\t|%d\t\t|%d\t|\n", i, parag[i].state, parag[i].length, parag[i].PTID);
    printf("所用表的信息:\n");
    printf("页号\t|状态\t|物理块号|\n");
    for(i = ptid; i<ptid+parag[did].length; i++)
        printf("%d\t|%d\t|%d\t|\n", i-ptid, page[i].state, page[i].MMID);
}

void Init()
{
    int i, d=0;
  
  for(i=0; i < n; i++)
  {
      parag[i].length=i+4;
      parag[i].state=1;
      parag[i].PTID=d;
      d+=parag[i].length;
  }

  for(i = 0; i < d; i++)
  {
      page[i].state=1;
      page[i].MMID=(i+7)%d;
  }
}

void Transform(int DID, int PID, int Address)
{
    if(DID >= n)
     {
         printf("段越界!\n");
         return;
     }
    if(parag[DID].length <= PID)
    {
        printf("页越界\n");
        return;
    }
    int ptid = parag[DID].PTID;
    int ptid2 = ptid+PID;
    int mmid = page[ptid2].MMID;
    int newAddress = 1024*mmid+Address;
    printf("转换前的地址:段号:%d, 页号:%d, 页内地址:%d\n",DID, PID, Address);
    print(DID,ptid);
    printf("物理地址为:%d", newAddress);
}
int main()
{
    int DID, PID, Address;
    Init();//初始化页表和段表
    printf("段号:\n");
    scanf("%d",&DID);
    printf("页号:\n");
    scanf("%d",&PID);
    printf("页内地址:\n");
    scanf("%d", &Address);
    Transform(DID, PID, Address);
    return 0;
}
  • 7
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
一. 实验目的: 1.通过编写和调试存储管理的模拟程序以加深对存储管理方案的理解。熟悉虚存管理的各种页面淘汰算法 2.通过编写和调试地址转换过程的模拟程序以加强对地址转换过程的了解。 .实验要求 实验程序由以下大部分组成: (1) 通过随机数产生一个指令序列(实际上是指令的逻辑地址序列),共320条指令。指令的地址按下述原则生成: A:50%的指令是顺序执行的 B:25%的指令要实现向前跳转,均匀分布在前地址部分 C:25%的指令要实现向后跳转,均匀分布在后地址部分 具体的实施方法是: A:在[0,319]的指令地址之间随机选取一起点m B:顺序执行一条指令,即执行地址为m+1的指令 C:在前地址[0,m+1]中随机选取一条指令并执行,该指令的地址为m’ D:顺序执行一条指令,其地址为m’+1 E:在后地址[m’+2,319]中随机选取一条指令并执行 F:重复步骤A-E,直到320次指令 (2) 将每条指令的逻辑地址变换为页地址 设:页面大小为1K; 用户内存容量4页到32页; 用户虚存容量为32K。 在用户虚存中,按每K存放10条指令排列虚存地址,即320条指令在虚存中的存放方式为: 第 0 条-第 9 条指令为第0页(对应逻辑地址为[0,9]) 第10条-第19条指令为第1页(对应逻辑地址为[10,19]) ……………………………… 第310条-第319条指令为第31页(对应逻辑地址为[310,319]) 按以上方式,用户指令可组成32页。 (3) 分别使用FIFO算法和LFU算法,计算给用户进程的这32页分配4,5,…,32个页面(内存块)时其缺页率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少年李富贵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值