介紹
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(PartiType *e1, PartiType e2);
Status InitList_Sq(SqList *L);
Status ListInsert_Sq(SqList *L,int i,PartiType e);
Status ListDelete_Sq(SqList *L,int i,PartiType *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(SqList *L, int i, PartiType e);
Status DeleteTable(SqList *L, int i, PartiType *e);
int SelectPart(PCB* pPCB, SqList *pPartTable, AllocatStrategy AS);
int MallocMemory(PCB *pe, SqList *pPartTable,int i);
void SearchSpace(PCBList PCBdata, SqList *partTable, AllocatStrategy AS);
void FreeMemory(int pos, SqList *pPartTable);
void InitAllocation(PCBList PCBdata, PartTable *partTable, AllocatStrategy AS);
void PrintProQueue(LinkList L);
void PrintPartTable(PartTable L);#endif
實現
list.c
#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->DistbutSt = e2.DistbutSt;e1->MemorySize = e2.MemorySize;e1->StartAddress = e2.StartAddress;
}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==iif (!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(PartiType *e1, PartiType e2)
{e1->PartitionSize = e2.PartitionSize;e1->PartStartAddr = e2.PartStartAddr;strcpy(e1->Name, e2.Name);
}Status InitList_Sq(SqList *L)
{//構造一個空的線性表LL->elem = (PartiType *)malloc((LIST_INIT_SIZE)*sizeof(PartiType));if(!L->elem) return ERROR; //存儲分配失敗L->length = 0; //空表長度為0L->listsize = LIST_INIT_SIZE; //初始存儲的容量return OK;
}//在順序線性表L中第i個位置之前插入新的元素e
Status ListInsert_Sq(SqList *L,int i,PartiType e)
{//在順序線性表L中第i個位置之前插入新的元素e//i的合法值為1 <= i <= ListLength_Sq(L)+1PartiType *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((p+1),*p); //插入位置及之后的元素右移PartiAssign(q ,e); //插入eL->length++;return OK;
}//在順序線性表L中刪除第i個元素,并用e返回其值
Status ListDelete_Sq(SqList *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(e, *p); //將被刪除元素的值賦給e (待定)q = L->elem + L->length-1; //移動到表尾元素的位置for (++p;p<=q;++p)PartiAssign((p-1), *p); //被刪除元素之后的元素左移L->length--;return OK;
}
?
#include "MemoryManage.h"
extern int CF_i;//***** 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(SqList *L, int i, PartiType e)
{return ListInsert_Sq(L,i, e);
}Status DeleteTable(SqList *L, int i, PartiType *e)
{return ListDelete_Sq(L, i, e);
}//返回第幾個內存塊,從1開始,若返回0,則代表錯誤
int SelectPart(PCB* pPCB, SqList *pPartTable,AllocatStrategy AS)
{int i;int BestArr[20] = {0}, k = 0, min = 500, min_i = -1;if(AS == FirstPriority){for (i = 0; i < pPartTable->length; ++i)if(!strcmp(pPartTable->elem[i].Name, "") && pPartTable->elem[i].PartitionSize >= pPCB->MemorySize)return i + 1;}else if(AS == BestAdapt){以下補充 /for(i = 0; i < pPartTable->length; ++i){if(!strcmp(pPartTable->elem[i].Name, "") && pPartTable->elem[i].PartitionSize >= pPCB->MemorySize)if(pPartTable->elem[i].PartitionSize - pPCB->MemorySize < min){min = pPartTable->elem[i].PartitionSize - pPCB->MemorySize;min_i = i;}}return min_i+1;}else if(AS == CycleFirst){int flag = 0;以下補充 /for(i = CF_i; i < pPartTable->length; i = (i+1)%(pPartTable->length)){if(!strcmp(pPartTable->elem[i].Name, "") && pPartTable->elem[i].PartitionSize >= pPCB->MemorySize){CF_i = (i+1)%pPartTable->length;return i + 1;}if(flag && i == CF_i){break;}if(i == CF_i){flag = 1;}}return 0;}else{printf("算法選擇有誤!\n");}return ERROR;
}//通過SelectPart查找是否存在可以分配的分區,在main函數中進行調用本方法進行內存的分配
int MallocMemory(PCB *pe, SqList *pPartTable,int i)
{PartiType se = {0, 0, {0}};以下補充 ///修改PCBpe->DistbutSt = Allocated;pe->StartAddress = pPartTable->elem[i].PartStartAddr;if(pPartTable->elem[i].PartitionSize == pe->MemorySize){strcpy(pPartTable->elem[i].Name, pe->Name);} else {//修改分區使用說明表strcpy(pPartTable->elem[i].Name, "");pPartTable->elem[i].PartitionSize -= pe->MemorySize;pPartTable->elem[i].PartStartAddr += pe->MemorySize;//新建一個表目, 并插入分區表使用說明表strcpy(se.Name, pe->Name);se.PartitionSize = pe->MemorySize;se.PartStartAddr = pe->StartAddress;InsertTable(pPartTable, i+1, se);}return OK;
}void InitAllocation(PCBList PCBdata, PartTable *pPartTable,AllocatStrategy AS)
{LNode *p;int pos;p = PCBdata->Next;while (p){if(p->data.DistbutSt == Unallocated){pos = SelectPart(&(p->data), pPartTable, AS);//從1開始if(pos){MallocMemory( &(p->data), pPartTable, pos - 1);}}p = p->Next;}
}//回收指定位置的內存空間
void FreeMemory(int pos, SqList *pPartTable)//沒考慮 pos為0情況,沒考慮刪除后修改起始地址情況
{PartiType se = {0, 0, {0}};int flag = 0;以下補充 /if(pos != pPartTable->length-1){//為后一塊分配if(!strcmp(pPartTable->elem[pos+1].Name, "")){strcpy(pPartTable->elem[pos].Name, "");pPartTable->elem[pos].PartitionSize += pPartTable->elem[pos+1].PartitionSize;strcpy(se.Name, pPartTable->elem[pos+1].Name);se.PartitionSize = pPartTable->elem[pos+1].PartitionSize;se.PartStartAddr = pPartTable->elem[pos+1].PartStartAddr;DeleteTable(pPartTable, pos+1, &se);flag = 1;}}if(pos != 0){//為前一塊分配if(!strcmp(pPartTable->elem[pos-1].Name, "")){strcpy(pPartTable->elem[pos-1].Name, "");pPartTable->elem[pos-1].PartitionSize += pPartTable->elem[pos].PartitionSize;strcpy(se.Name, pPartTable->elem[pos-1].Name);se.PartitionSize = pPartTable->elem[pos-1].PartitionSize;se.PartStartAddr = pPartTable->elem[pos-1].PartStartAddr;DeleteTable(pPartTable, pos-1, &se);flag = 1;}}if(!flag){strcpy(pPartTable->elem[pos].Name, "");}
}void SearchSpace(PCBList PCBdata, SqList *partTable, AllocatStrategy AS)
{int pos;LNode *p;p = PCBdata->Next;while (p){if(p->data.DistbutSt == Unallocated){pos = SelectPart(&(p->data), partTable, AS);//從1開始if(pos){MallocMemory(&(p->data), partTable, pos - 1);}}p = p->Next;}}void PrintProQueue(LinkList L)
{int i = 0;L = L->Next;printf(" ----------------------------------------\n");printf("|進程名 | 起始位置 | 申請大小 | 是否分配 |\n");while(L){printf("| %s | %4d | %4d | %4s |\n",L->data.Name, L->data.StartAddress, L->data.MemorySize, L->data.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 + 1 , L.elem[i].PartStartAddr, L.elem[i].PartitionSize , strcmp(L.elem[i].Name, "") ? L.elem[i].Name :"否");printf(" ----------------------------------------\n");
}
main
#include "MemoryManage.h"/*實驗06 動態分區分配
*/int CF_i;void InputPCBData(PCBList * pPCBdata)
{PCBType e = {{0}, 0, 0, Unallocated};strcpy(e.Name,"P1");e.MemorySize = 16;InsertProcess(*pPCBdata,e);strcpy(e.Name,"P2");e.MemorySize = 32;InsertProcess(*pPCBdata,e);strcpy(e.Name,"P3");e.MemorySize = 48;InsertProcess(*pPCBdata,e);strcpy(e.Name,"P4");e.MemorySize = 96;InsertProcess(*pPCBdata,e);strcpy(e.Name,"P5");e.MemorySize = 100;InsertProcess(*pPCBdata,e);
}void SetFixedZone(PartTable * pPartdata)
{PartiType se = {0, 0, {0}};se.PartStartAddr = 16;se.PartitionSize = 512 - 16;strcpy(se.Name, "");InsertTable(pPartdata, 1, se);
}
//0 - 15Kb 操作系統占用 總大小512KB
int main(void)
{PCBList PCBdata; //PCBdata里面存放原始PCB數據PartTable partTable; //分區表char PcbName[NAME_MAXSIZE] = {0}, choice;PCBType PCBe = {{0}, 0, 0, Unallocated};PartiType Parte = {0, 0};PCBType *pcb = NULL;LNode *p; AllocatStrategy AS = CycleFirst; //FirstPriority, BestAdapt, CycleFirst//AllocatStrategy AS = BestAdapt;int i, size, pos;//分區表InitList_Sq(&partTable);SetFixedZone(&partTable);//進程表InitLinkList(&PCBdata);InputPCBData(&PCBdata);//初始化InitAllocation(PCBdata, &partTable, AS);CF_i = 0;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);for(i = 0; i < partTable.length; i++){if(!strcmp(PcbName, partTable.elem[i].Name)){FreeMemory(i ,&partTable);break;}}SearchSpace( PCBdata, &partTable, AS);break;case '2':printf("請輸入添加的進程名,進程所占內存大小:");scanf("%s%d",PcbName , &size);PCBe.DistbutSt = Unallocated;PCBe.StartAddress = 0;strcpy(PCBe.Name, PcbName);PCBe.MemorySize = size;pos = SelectPart(&(PCBe), &partTable, AS);//從1開始if(pos)MallocMemory(&(PCBe), &partTable, pos - 1);InsertProcess(PCBdata, PCBe);break;case '3':return 0;default:printf("選擇項輸入錯誤,重新選擇!\n");break;}PrintProQueue(PCBdata);PrintPartTable(partTable);system("pause");}return 0;
}
?