存储器管理子系统
1.模块设计内容
某进程并发度最大为10的计算机系统中,内存采用虚拟分页存储管理方式,页长为2KB,逻辑地址为32位,物理地址为24位,内存页框的分配和回收采用位示图法,页面置换采用LRU算法,请根据你所学到的知识,编程实现这个存储管理系统。
2.模块设计要求
(1)首先装入OS内核,占两个页框。
即位示图的前连个块默认被占用
(2)位示图有多大?占用怎样的内存空间?请说明,并编程输出初始状态。
页长为2KB,即页的大小为2的11次方字节,2的24次方除以2的11次方得2的13次方个页框,即如果每行8个块(位示图数字为0和1,0为未被占用,1为已经被使用),需要打印1000行方可将位示图全部打印出来,但是这里为了体现LRU算法的执行情况,只打印两行,相当于给分配了14个页框。
(3)每个进程的页表怎么设计?怎么存储?请说明。
一个进程对应一个页表,包含页号、块号、进程最近被访问时间,初始为0。
(4)为若干进程分配内存空间,请输出每次装入一个进程后的位示图和页表。
(5)按某个页面引用序列执行一个进程,请输出其页面装入和置换过程。
为了实现LRU算法,该算法的进程调度为时间片轮转法调度,页面为随机调取
有不懂的地方可以留言询问
#include <stdio.h> //编译预处理,引用标准函数库中的输入输出
#include <stdlib.h> //引用杂项函数及内存分配函数
#include <time.h> //引用时间处理函数
#include <math.h> //引用数学函数
#include <string.h> //引用字符串处理函数
/**
打“<>”这种尖括号,说的是,这个文件是编程环境标配拥有的文件,到默认的标配的地方去找这个文件
打引号,表示这不是编程环境标配拥有的文件,要在你的工程文件所在的目录中找,或是在编程环境设定中要查找的目录中去找。
*/
//宏定义,不占内存,在编译之前处理,是为常量,不可更改。
#define N 8 //定义每行的位示图的最大块数,每块128kB,一行为1024KB,也即1M,2的10次方
#define page_len 2 //页长 2KB
#define blockSize 2 //块大小2KB
int empty_block = 16; //空块个数,页框数,这里的大小定义将决定LRU算法是否会执行以及执行的频率
int page; //进程页数
int Ltimes; //程序时间
typedef struct page_trend{
int process_name;
int page_name;
int *next;
}pat;
/**
进程控制块结构体
包括:进程名称,进程剩余执行时间、进程大小以及下一个进程的地址next
*/
typedef struct PCB{
//进程控制块
int priority; //进程优先级
int name; //进程名称
int times;//进程运行时间
int p_prioruity; //进程优先级
struct PCB *next;
int sizeKB;//进程大小
}pcb;
// typedef,为结构体去一个新的名字
/**
父链表结构体
包括:
进程页数
进程名称
子链头指针
下一个父链表地址next
*/
typedef struct pts{
//父链表结构
int priority; //进程优先级
int process;//进程名称
int p_amount;//进程页数
struct pt *pHead; //指向子链表头
struct pts *next; //指向下一个父链表
}PTS;
/**
子链表结构体
包括:
页号(逻辑地址)
块号(物理地址)
最近访问时间
下一个子链表地址next
*/
typedef struct pt{
//子链表(页表)结构
int p_number;//页号
int p_block;//块号
int LRUtime;//进程最近被访问时间
struct pt *next;
}pt;
// 方法名放在结构体的下方,代码块的上方(记得加分号)。
pcb *Init(void);//初始化链表
pcb *create(pcb *head,int num);//创建单链表
void Traverl_all(pcb *head);//遍历所有链表信息
void Traverl_one(pcb *p);//遍历一行链表信息
void init_graph(int g[N][N]);//1、初始化位示图
void print_graph(int g[N][N]);//2、打印位示图
PTS *Init_Father_Table(void);//3、初始化父链
PTS *create_table(pcb *head,PTS *T_head);//4、创建父链
void print_table_one(PTS *T_head);//5、打印父链表
int isIn(PTS *tp,int amount);//判断页面是否装入
pt *create_page(int amount,PTS *tp,int i,int j,int g[N][N]);//6、创建子链
void init_pageTable(pcb *head,PTS *T_head,int num,int g[N][N]);//7、初始化页表
void print_table_two(PTS *T_head);//8、打印子链表
void LRU(int g[N][N],PTS *T_head);//9、LRU淘汰算法
int Sort1(pcb *head);
//对进程的优先级进行排序
int Sort1(pcb *head) //参数为头指针,传值时传入头指针的地址
{
pcb *q, *p, *tail, *temp;
tail = NULL; //将链表的尾部置为NULL
q = head; //将链表的头指针地址赋值给q,从而进行操作
while((head->next) != tail) //如果还没跑到链表的尾部,则继续执行
{
p = head->next;
q = head;
while(p->next != tail) //链表没跑到尾部,继续执行
{
//将优先级低的进程放到链表的尾部
if((p->priority) > (p->next->priority)){
//如果p的优先级没有下一个节点的优先级高(优先级的数字越小,优先级越高)
q->next = p->next;
temp = p->next->next;
p->next->next = p;
p->next = temp;
p = q->next;
}
p = p->next; //指针后移,继续比较
q = q->next;
}
tail = p;
}