模拟基本分页存储

介绍

data.h

#ifndef _Data_h_
#define _Data_h_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#define LIST_INIT_SIZE 10
#define LISTINCREMENT  2
#define true				1
#define false				0
#define PCBType				PCB
#define Status				int
#define OK					1
#define	ERROR				0
#define NAME_MAXSIZE		20
#define PCB_Num				5
#define LIST_INITSIZE		10
#define PartiType			PartitionInfo
#define BlockNumType		PageData //分页信息
#define TotalMemory			512	//KB
#define PageSize			16	//通常为1 ~ 8KB    //进程申请内存的大小[16, 256]KB    256 / 8 = 32页


typedef enum 
{
	Unallocated, Allocated
}DistributState, PartitionSt;

typedef struct {
							//分区号用数组下标代替
	int PartStartAddr;
	char Name[NAME_MAXSIZE];//若为空,则分区空闲
}PartitionInfo;

typedef struct
{
	PartitionInfo *elem;
	int listsize;		//表容量
	int length;			//元素个数
}SqList_f, PartTable;	//分区使用说明表


typedef struct {					    
	int BlockNum;               //块号
	DistributState DistbutSt;	//分配状态
}PageData;


typedef struct
{
	PageData *elem;	
	int listsize;		
	int length;			
}SqList_y, PageTable;	//页表


typedef struct 
{
	char Name[NAME_MAXSIZE];	//进程名
	int	MemorySize;				//内存的大小
	PageTable *pPagetable;		//页表指针
}PCB;

typedef struct Node
{
	PCBType data;
	struct Node * Next;		
}LNode, *LinkList, *PCBList;


#endif 

list.h

#ifndef _List_h_
#define _List_h_

#include "Data.h"

//*******           链表            *******//
Status InitLinkList(LinkList *L);
void PCBAssign(PCBType *e1, PCBType e2);
Status GetElemt_L(LinkList L,int i,PCBType *e);
Status ListInsert_L(LinkList L,PCBType e);
Status ListDelete_L(LinkList L,int i,PCBType *e);

//******         分区使用说明表           ******//
void PartiAssign_f(PartiType *e1, PartiType e2);
Status InitList_f(SqList_f *L);
Status ListInsert_f(SqList_f *L,int i,PartiType e);
Status ListDelete_f(SqList_f *L,int i,PartiType *e);


//******         页表           ******//
void PartiAssign_y(BlockNumType *e1, BlockNumType e2);
Status InitList_y(SqList_y **L);
Status ListInsert_y(SqList_y *L,int i,BlockNumType e);
Status ListDelete_y(SqList_y *L,int i,BlockNumType *e);

#endif

memorymanage.h

#ifndef _MemoryManage_h_
#define _MemoryManage_h_

#include "List.h"

//*****         PCB 链 表 操 作        *****//
Status InsertProcess(LinkList Q,PCBType e);
Status DeleteProsess(LinkList Q,int i,PCBType *e);
//*****         分 区 表 操 作         *****//
//插入分区表元素
Status InsertTable_f(SqList_f *L, int i, PartiType e);	
//删除分区表元素
Status DeleteTable_f(SqList_f *L, int i, PartiType *e);


//******          页 表 操 作         ******//
//插入页表元素
Status InsertTable_y(SqList_y *L, int i, BlockNumType e);
//删除页表元素
Status DeleteTable_y(SqList_y *L, int i, BlockNumType *e);
Status LoadPages(PageTable *L, int size);

Status MallocMemory(PCB *pe, SqList_f *pPartTable, int *arr);
Status SelectPart(PCB* pPCB, SqList_f *pPartTable,int *arr);
void SearchSpace(PCBList PCBdata, SqList_f *partTable);
void FreeMemory(int *arr, int len, SqList_f *pPartTable);
void InitAllocation(PCBList PCBdata, PartTable *partTable);
void PrintProQueue(LinkList L);
void PrintPartTable(PartTable L);




#endif

实现

#include "List.h"


//*******           链表            *******//
Status InitLinkList(LinkList *L)
{
	*L = (LinkList)malloc(sizeof(LNode));
	strcpy((*L)->data.Name, "");
	(*L)->Next = NULL;
	return OK;
}

void PCBAssign(PCBType *e1, PCBType e2)
{
	strcpy(e1->Name,e2.Name);
	e1->MemorySize = e2.MemorySize;
	e1->pPagetable = e2.pPagetable;
}

Status GetElemt_L(LinkList L,int i,PCBType *e)
{
	LinkList p = L->Next;	//指向第j个结点
	int j = 1;				//从第一个开始往后找
	while ( p && j < i )	//p不为空且j < i
	{
		p = p->Next;
		++j;
	}						//p为空,说明链表循环结束,也没有到第i个结点   j==i
	if (!p || j > i)		//因为此处对i   没有做判断   如果 i==0  或 负数  条件成立
							//对于 i == j == 1 的情况则不用循环正好  返回
	{
		return ERROR;
	}
	*e = p->data;			//通过寻址改变了 该地址内存中元素的值
	return OK;
}
//链表中按照优先级:从大到小排序插入
Status ListInsert_L(LinkList L,PCBType e)	//这样修改应该不对 p = *L出错
{
	LinkList p = L, s;
	while (p->Next)	
		p = p->Next;
	s = (LinkList)malloc(sizeof(LNode));
	PCBAssign(&s->data, e);
	s->Next = p->Next;
	p->Next = s;
	return OK;
}

Status ListDelete_L(LinkList L,int i,PCBType *e)
{
	LinkList p = L, q;
	int j = 0;
	while (p->Next && j < i-1)
	{
		p = p->Next; ++j;
	}
	if(!p->Next || j > i - 1)
		return ERROR;
	q = p->Next;
	p->Next = q->Next;
	PCBAssign(e, q->data);
	free(q);
	return OK;
}

//******         分区使用说明表           ******//
void PartiAssign_f(PartiType *e1, PartiType e2)
{
	e1->PartStartAddr = e2.PartStartAddr;
	strcpy(e1->Name, e2.Name);
}

Status InitList_f(SqList_f *L)
{
	//构造一个空的线性表L
	L->elem = (PartiType *)malloc((LIST_INIT_SIZE)*sizeof(PartiType));
	if(!L->elem) return ERROR;        //存储分配失败
	L->length = 0;                 //空表长度为0
	L->listsize = LIST_INIT_SIZE;  //初始存储的容量
	return OK;
}

//在顺序线性表L中第i个位置之前插入新的元素e
Status ListInsert_f(SqList_f *L,int i,PartiType e)
{
	//在顺序线性表L中第i个位置之前插入新的元素e
	//i的合法值为1 <= i <= ListLength_Sq(L)+1
	PartiType *q, *p, *newbase;

	if(i < 1 || i > L->length + 1 ) return ERROR;     //i值不合法
	if(L->length >= L->listsize){               //当前存储空间已满,增加分配
		newbase = (PartiType *)realloc(L->elem
			,(L->listsize + LISTINCREMENT)*sizeof(PartiType));
		if(!newbase) return ERROR;				//存储分配失败
		L->elem = newbase;						//新基址
		L->listsize += LISTINCREMENT;			//增加存储容量
	} 
	q = &(L->elem[i - 1]);			         	//q为插入位置
	for(p = &(L->elem[L->length-1]);p >= q; --p)
		PartiAssign_f((p+1),*p); 					//插入位置及之后的元素右移
	PartiAssign_f(q ,e);							//插入e
	L->length++;
	return OK;
}

//在顺序线性表L中删除第i个元素,并用e返回其值
Status ListDelete_f(SqList_f *L,int i,PartiType *e)
{
	//在顺序线性表L中删除第i个元素,并用e返回其值
	//i的合法值为1 <= i <= ListLength_Sq(L)
	PartiType *p,*q;
	if((i < 1) || (i > L->length))	
		return ERROR;							 //i值不合法
	p = &(L->elem[i-1]);						 //p为被删除元素的位置
	PartiAssign_f(e, *p);							 //将被删除元素的值赋给e (待定)
	q = L->elem + L->length-1;					 //移动到表尾元素的位置
	for (++p;p<=q;++p)
		PartiAssign_f((p-1), *p);					 //被删除元素之后的元素左移
	L->length--;
	return OK;
}


//******         页表           ******//

void PartiAssign_y(BlockNumType *e1, BlockNumType e2)
{
	(*e1).BlockNum = e2.BlockNum;
    (*e1).DistbutSt = e2.DistbutSt;
}

Status InitList_y(SqList_y **L)
{
	//构造一个空的线性表L
    (*L) = (PageTable *)malloc(sizeof(PageTable));//不可缺少
	(*L)->elem = (BlockNumType *)malloc((LIST_INIT_SIZE)*sizeof(BlockNumType));
	if(!(*L)->elem) return ERROR;        //存储分配失败
	(*L)->length = 0;                 //空表长度为0
	(*L)->listsize = LIST_INIT_SIZE;  //初始存储的容量
	return OK;
}

//在顺序线性表L中第i个位置之前插入新的元素e
Status ListInsert_y(SqList_y *L,int i,BlockNumType e)
{
	//在顺序线性表L中第i个位置之前插入新的元素e
	//i的合法值为1 <= i <= ListLength_Sq(L)+1
	BlockNumType *q, *p, *newbase;

	if(i < 1 || i > L->length + 1 ) return ERROR;     //i值不合法
	if(L->length >= L->listsize){               //当前存储空间已满,增加分配
		newbase = (BlockNumType *)realloc(L->elem
			,(L->listsize + LISTINCREMENT)*sizeof(BlockNumType));
		if(!newbase) return ERROR;				//存储分配失败
		L->elem = newbase;						//新基址
		L->listsize += LISTINCREMENT;			//增加存储容量
	} 
	q = &(L->elem[i - 1]);			         	//q为插入位置
	for(p = &(L->elem[L->length-1]);p >= q; --p)
		PartiAssign_y((p+1),*p); 					//插入位置及之后的元素右移
	PartiAssign_y(q ,e);							//插入e
	L->length++;
	return OK;
}

//在顺序线性表L中删除第i个元素,并用e返回其值
Status ListDelete_y(SqList_y *L,int i,BlockNumType *e)
{
	//在顺序线性表L中删除第i个元素,并用e返回其值
	//i的合法值为1 <= i <= ListLength_Sq(L)
	BlockNumType *p,*q;
	if((i < 1) || (i > L->length))	
		return ERROR;							 //i值不合法
	p = &(L->elem[i-1]);						 //p为被删除元素的位置
	PartiAssign_y(e, *p);							 //将被删除元素的值赋给e (待定)
	q = L->elem + L->length-1;					 //移动到表尾元素的位置
	for (++p;p<=q;++p)
		PartiAssign_y((p-1), *p);				 //被删除元素之后的元素左移
	L->length--;
	return OK;
}

memorymanage.c


#include "MemoryManage.h"

//*****         PCB链表操作        *****//
Status InsertProcess(LinkList Q,PCBType e)
{
	return ListInsert_L(Q, e);
}

Status DeleteProsess(LinkList Q,int i,PCBType *e)
{
	return ListDelete_L(Q ,i,e);
}

//*****         分区表操作        *****//
Status InsertTable_f(SqList_f *L, int i, PartiType e) 
{
	return ListInsert_f(L,i, e);
}

Status DeleteTable_f(SqList_f *L, int i, PartiType *e)
{
	return ListDelete_f(L, i, e);
}

//*****         页表操作        *****//
Status InsertTable_y(SqList_y *L, int i, BlockNumType e)
{
	return ListInsert_y(L,i, e);
}

Status DeleteTable_y(SqList_y *L, int i, BlockNumType *e)
{
	return ListDelete_y(L, i, e);
}

Status LoadPages(PageTable *L, int size)
{
    int i, pageNum = ceil( size * 1.0 / PageSize) ;
    PageData e = {-1, Unallocated};
    for (i = 0; i < pageNum; i++)
    {
        if(!InsertTable_y(L, L->length + 1, e))
            return ERROR;
    }
    return OK;;
}

//若返回0,则代表错误
Status SelectPart(PCB* pPCB, SqList_f *pPartTable,int *arr)
{
	/     以下补充     /
    int i = 0, j = 0;

	while(i < pPCB->pPagetable->length && j < pPartTable->length){
		if(pPCB->pPagetable->elem[i].DistbutSt == Unallocated){
			if(!strcmp(pPartTable->elem[j].Name, "")){
				arr[i] = j;
				++i;
				++j;
			} else {
				++j;
			}
		} else {
			++i;
		}
	}

	if(i == pPCB->pPagetable->length){
		return OK;
	}
    return ERROR;
}

Status MallocMemory(PCB *pe, SqList_f *pPartTable, int *arr)
{
    int i, pageNum ;
   
	      以下补充     /
	for(i = 0; i < pe->pPagetable->length; ++i){
		if(pe->pPagetable->elem[i].DistbutSt == Unallocated){
			pe->pPagetable->elem[i].BlockNum = arr[i];
			pe->pPagetable->elem[i].DistbutSt = Allocated;

			strcpy(pPartTable->elem[arr[i]].Name, pe->Name);
		}
	}
	
	return ERROR;
}

void InitAllocation(PCBList PCBdata, PartTable *pPartTable)
{
	LNode *p;
    int pos, arr[20] = {0};
	p = PCBdata->Next;
	while (p)
	{
		if(p->data.pPagetable->elem[0].DistbutSt == Unallocated)
		{
			if(SelectPart(&(p->data), pPartTable, arr))
			{
				MallocMemory(&(p->data), pPartTable, arr);
			}
		}
		p = p->Next;
	}
}

//该释放进程只在结束进程时用到,因此不用管进程信息
void FreeMemory(int *arr, int len, SqList_f *pPartTable)
{
    int i;
	     以下补充   /
	for(i = 0; i < len; ++i){
		strcpy(pPartTable->elem[arr[i]].Name, "");
	}
}

void SearchSpace(PCBList PCBdata, SqList_f *partTable)
{
    int pos, arr[20] = {0};
	LNode *p;
	p = PCBdata->Next;
	while (p)
	{
		if(p->data.pPagetable->elem[0].DistbutSt == Unallocated)
		{
			if(SelectPart(&(p->data), partTable, arr))
			{
				MallocMemory(&(p->data), partTable, arr);
			}
		}
		p = p->Next;
	}

}

void PrintProQueue(LinkList L)
{
	int i = 0;

	L = L->Next;
	
	while(L)
	{
        printf(" -----------------------------\n");
        printf("|进程名 | 申请大小 |\n");
        printf("|  %s   |  %4d    |\n", L->data.Name, L->data.MemorySize);

            printf("%s页表信息如下:\n|   页号   |   块号   | 是否分配 |\n", L->data.Name);
            for (i = 0; i < L->data.pPagetable->length; i++)
                printf("|  %4d    |  %4d    |  %4s    |\n", i , L->data.pPagetable->elem[i].BlockNum,
                        L->data.pPagetable->elem[i].DistbutSt == Allocated?  "是" : "否");
		L = L->Next;
	}
	printf(" ----------------------------------------\n");
}

void PrintPartTable(PartTable L)
{
	int i = 0, j = 0;
	printf(" ----------------------------------------\n");
	printf("|分区号 | 起始位置 | 分区大小 | 是否分配 |\n");
	for (i = 0; i < L.length; ++i)
		printf("|  %2d   |  %4d    |  %4d    |  %4s    |\n",
			i , L.elem[i].PartStartAddr, PageSize , strcmp(L.elem[i].Name, "") ? L.elem[i].Name :"否");
	printf(" ----------------------------------------\n");
}

main

#include "MemoryManage.h"

/*   实验08  基本分页   */

void InputPCBData(PCBList * pPCBdata)
{
	PCBType e = {{0}, 0, NULL};
    
	strcpy(e.Name,"P1");
	e.MemorySize = 16;
    InitList_y(&(e.pPagetable));
    LoadPages(e.pPagetable, e.MemorySize);
	InsertProcess(*pPCBdata,e);

	strcpy(e.Name,"P2");
	e.MemorySize = 32;
    InitList_y(&(e.pPagetable));
    LoadPages(e.pPagetable, e.MemorySize);
	InsertProcess(*pPCBdata,e);

	strcpy(e.Name,"P3");
	e.MemorySize = 48;
    InitList_y(&(e.pPagetable));
    LoadPages(e.pPagetable, e.MemorySize);
	InsertProcess(*pPCBdata,e);

	strcpy(e.Name,"P4");
	e.MemorySize = 96;
    InitList_y(&(e.pPagetable));
    LoadPages(e.pPagetable, e.MemorySize);
	InsertProcess(*pPCBdata,e);

	strcpy(e.Name,"P5");
	e.MemorySize = 100;
    InitList_y(&(e.pPagetable));
    LoadPages(e.pPagetable, e.MemorySize);
	InsertProcess(*pPCBdata,e);
}

void SettingPage(PartTable * pPartdata)
{
	PartiType se = {0, {0}};
	int Num = (512 - 16) / PageSize , i;
	for (i = 0; i < Num; ++i)
	{
		se.PartStartAddr = 16 + i * PageSize;
		InsertTable_f(pPartdata, i + 1, se);
	}
}
//0 - 15Kb 操作系统占用  总大小512KB
int main(void)
{
	PCBList PCBdata;		//PCBdata里面存放原始PCB数据
	PartTable partTable;	//分区表
	char PcbName[NAME_MAXSIZE] = {0}, choice;
	PCBType PCBe = {{0}, 0, NULL};
	PartiType Parte = {0, 0};
	PCBType *pcb = NULL;
	LNode *p; 
	
    int i, size, pos, arr[20] = {0}, k = 0;

	InitList_f(&partTable);
	SettingPage(&partTable);
	InitLinkList(&PCBdata);
	InputPCBData(&PCBdata);

	InitAllocation(PCBdata, &partTable);

	PrintProQueue(PCBdata);
	PrintPartTable(partTable);
	
	while(true)
	{
		system("cls");
		PrintProQueue(PCBdata);
		PrintPartTable(partTable);
		printf(" ================================================\n");
		printf("|           1.结 束 进 程                        |\n");
		printf("|           2.添 加 进 程                        |\n");
		printf("|           3.退 出 系 统                        |\n");
		printf(" ================================================\n");
		printf("请选择:");
		fflush(stdin);
		scanf("%c",&choice);
		
		switch (choice)
		{
		case '1':
			printf("要结束的进程名:");
			scanf("%s",PcbName);
			for (p = PCBdata->Next, i = 1; p && strcmp(PcbName, p->data.Name); i++, p = p->Next);
			if(!p)
			{
				printf("进程名输入错误!\n");
				break;
			}
			DeleteProsess(PCBdata, i, &PCBe);
            k = 0;
			for(i = 0; i < partTable.length; i++)
			{
				if(!strcmp(PcbName, partTable.elem[i].Name))
				{
					arr[k++] = i;
				}
			}
            FreeMemory(arr, k, &partTable);

			SearchSpace(PCBdata, &partTable);
			break;
		case '2':
			printf("请输入添加的进程名,进程所占内存大小:");
			scanf("%s%d",PcbName , &size);
			strcpy(PCBe.Name, PcbName);
			PCBe.MemorySize = size;
            InitList_y(&(PCBe.pPagetable));
            LoadPages(PCBe.pPagetable, PCBe.MemorySize);
			if(SelectPart(&(PCBe), &partTable, arr))
				MallocMemory(&(PCBe), &partTable, arr);
			InsertProcess(PCBdata, PCBe);
			break;
		case '3':
			return 0;

		default:
			printf("选择项输入错误,重新选择!\n");
			break;
		}
		PrintProQueue(PCBdata);
		PrintPartTable(partTable);
		system("pause");
	}

	return 0;
}

 

  • 11
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

兔老大RabbitMQ

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

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

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

打赏作者

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

抵扣说明:

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

余额充值