小言_互联网的博客

超硬核!学霸把操作系统经典算法给敲完了!要知行合一

404人阅读  评论(0)

上期的笔记,浏览快1万了,既然关注的人很多,那就发出来承诺过的算法全模拟,希望帮到你们。

上期的操作系统学霸笔记,考试复习面试全靠它

一、模拟进程调度

功能

data.h


  
  1. #ifndef _Data_h_
  2. #define _Data_h_
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #define ElemType PCB
  7. #define Status int
  8. #define OK 1
  9. #define ERROR 0
  10. #define TimeSlice 1
  11. #define Infinity 10 //INT_MAX
  12. #define NAME_MAXSIZE 20
  13. typedef enum
  14. {
  15. Ready,Running,Block
  16. }ProState;
  17. typedef enum
  18. {
  19. FCFS, SPF //先来先服务,短进程优先
  20. }PriorityRule;
  21. typedef struct
  22. {
  23. char Name[NAME_MAXSIZE]; //进程名
  24. int Priority; //优先数
  25. int ArrivalTime; //到达时间 以时间片为单位
  26. int NeedRunningTime; //运行时间 以时间片为单位
  27. int StartTime; //开始执行时间
  28. int FinishTime; //完成时间
  29. int TimeUsedCPU; //已用CPU时间 以时间片为单位
  30. ProState ProcessState; //进程状态
  31. }PCB;
  32. typedef struct Node
  33. {
  34. ElemType data;
  35. struct Node * Next;
  36. }LNode,*LinkList;
  37. #endif

 ChainList.h


  
  1. #ifndef _ChainList_h_
  2. #define _ChainList_h_
  3. #include "Data.h"
  4. //功能:链表初始化
  5. Status Init(LinkList *L);
  6. //功能:赋值运算,将e2赋值给e1
  7. void Assignment(ElemType *e1, ElemType e2);
  8. //功能:获取第i个结点元素
  9. Status GetElemt_L(LinkList L,int i,ElemType *e);
  10. //功能:链表根据优先级插入元素
  11. Status ListInsert_L(LinkList L,ElemType e);
  12. //功能:链表删除头结点
  13. Status ListDelete_L(LinkList L,ElemType *e);
  14. #endif

ProPCB.h


  
  1. #ifndef _ProPCB_h_
  2. #define _ProPCB_h_
  3. #include "ChainList.h"
  4. //功能:将e插入链表Q
  5. Status GetProcess(LinkList Q,ElemType e); //上就绪队列
  6. //功能:根据不同的优先级规则,返回优先数
  7. int GetPriority(ElemType *e, PriorityRule PR); //根据不同的规则PR 设置优先数
  8. //功能:将链表Q的头结点数据放到e指向的内存,并删除
  9. Status OutProsess(LinkList Q,ElemType *e); //下就绪队列
  10. //功能:CPU运行pcb指向的进程,并输出所有进行进程状态
  11. Status CPURunPro(LinkList Q, PCB *pcb); //CPU运行PCB
  12. //功能:打印所有PCB信息
  13. void PrintProQueue(LinkList Q, PCB *pcb); //打印运行后PCB信息
  14. //功能:当一个进程结束,打印进程信息
  15. void PrintProResult(PCB *pcb);
  16. #endif

实现


  
  1. #include "ChainList.h"
  2. extern int CPUUsedTime;
  3. //功能:链表初始化
  4. Status Init(LinkList *L)
  5. {
  6. *L = (LinkList) malloc( sizeof(LNode));
  7. (*L)->data.NeedRunningTime = -1;
  8. (*L)->Next = NULL;
  9. return OK;
  10. }
  11. //功能:赋值运算,将e2赋值给e1
  12. void Assignment(ElemType *e1, ElemType e2)
  13. {
  14. e1->ArrivalTime = e2.ArrivalTime;
  15. strcpy(e1->Name,e2.Name);
  16. e1->Priority = e2.Priority;
  17. e1->ProcessState = e2.ProcessState;
  18. e1->FinishTime = e2.FinishTime;
  19. e1->StartTime = e2.StartTime;
  20. e1->NeedRunningTime = e2.NeedRunningTime;
  21. e1->TimeUsedCPU = e2.TimeUsedCPU;
  22. }
  23. //链表中按照优先级:从大到小排序插入
  24. Status ListInsert_L(LinkList L,ElemType e) //这样修改应该不对 p = *L出错
  25. {
  26. LinkList p = L->Next, pre = L, s;
  27. while (p && e.Priority <= p->data.Priority)
  28. {
  29. pre = p;
  30. p = p->Next;
  31. }
  32. s = (LinkList) malloc( sizeof(LNode));
  33. Assignment(&s->data, e);
  34. s->Next = pre->Next;
  35. pre->Next = s;
  36. return OK;
  37. }
  38. //链表中头部删除
  39. Status ListDelete_L(LinkList L,ElemType *e)
  40. {
  41. LinkList p = L, q;
  42. q = p->Next;
  43. if(!q)
  44. return ERROR;
  45. p->Next = q->Next;
  46. Assignment(e, q->data);
  47. free(q);
  48. return OK;
  49. }

  
  1. #include "ProPCB.h"
  2. extern int CPUUsedTime;
  3. //功能:将e插入链表Q
  4. Status GetProcess(LinkList Q,ElemType e)
  5. {
  6. return ListInsert_L(Q, e);
  7. }
  8. //功能:根据不同的优先级规则,返回优先数
  9. int GetPriority(ElemType *e, PriorityRule PR)
  10. {
  11. if(PR == FCFS)
  12. return Infinity - e->ArrivalTime;
  13. else if(PR == SPF)
  14. return Infinity - e->NeedRunningTime;
  15. else
  16. printf( "GetPriority Function ERROR!\n");
  17. return ERROR;
  18. }
  19. //功能:将链表Q的头结点数据放到e指向的内存,并删除
  20. Status OutProsess(LinkList Q,ElemType *e)
  21. {
  22. return ListDelete_L(Q ,e);
  23. }
  24. //上一次CPU运行时间增加1个时间片
  25. Status CPURunPro(LinkList Q,PCB *pcb)
  26. {
  27. if(pcb->StartTime == -1)
  28. pcb->StartTime = CPUUsedTime;
  29. pcb->ProcessState = Running;
  30. //PrintProQueue(Q, pcb);
  31. pcb->TimeUsedCPU += TimeSlice;
  32. return OK;
  33. }
  34. //功能:打印所有PCB信息
  35. void PrintProQueue(LinkList Q, PCB *pcb)
  36. {
  37. LinkList p = Q->Next;
  38. printf( "进程名 优先数 到达时间 运行时间 已用CPU时间 完成时间 进程状态\n");
  39. if(pcb)
  40. printf( " %4s %2d %4d %4d %3d(+1) %3d %4s \n",
  41. pcb->Name,pcb->Priority,pcb->ArrivalTime,pcb->NeedRunningTime,
  42. pcb->TimeUsedCPU, pcb->FinishTime,pcb->ProcessState == Ready ? "就绪" : "运行");
  43. while (p)
  44. {
  45. printf( " %4s %2d %4d %4d %3d %3d %4s \n",
  46. p->data.Name,p->data.Priority,p->data.ArrivalTime,p->data.NeedRunningTime,
  47. p->data.TimeUsedCPU,p->data.FinishTime, p->data.ProcessState == Ready ? "就绪" : "运行");
  48. p = p->Next;
  49. }
  50. printf( "-------------------------------------------------------------------------------\n");
  51. }
  52. //功能:当一个进程结束,打印进程信息
  53. void PrintProResult(PCB *pcb)
  54. {
  55. printf( "进程名 到达时刻 运行时间 开始时刻 完成时刻 周转时间 带权周转时间 进程状态\n");
  56. if(pcb)
  57. printf( " %2s %3d %4d %4d %3d %4d %5.2lf %4s \n",
  58. pcb->Name,pcb->ArrivalTime,pcb->NeedRunningTime,pcb->StartTime,pcb->FinishTime,
  59. pcb->FinishTime-pcb->ArrivalTime,((pcb->FinishTime - pcb->ArrivalTime)* 1.0)/pcb->NeedRunningTime, "完成");
  60. printf( "-------------------------------------------------------------------------------\n");
  61. }

main:


  
  1. #include "ProPCB.h"
  2. /****************************
  3. * 实验01: 非抢占式静态优先权 *
  4. * ① 优先权始终保持不变 *
  5. * ② 一旦进入CPU便运行到结束 *
  6. * ③ FCFS只考虑到达时间进CPU *
  7. * ④ SPF认为到达时间相同 *
  8. ****************************/
  9. int CPUUsedTime = 0;
  10. void InputData(LinkList * pPCBdata, PriorityRule PR)
  11. {
  12. ElemType e = {{ 0}, -1, -1, -1, -1, -1, 0,Ready};
  13. e.ArrivalTime = 0;
  14. e.ProcessState = Ready;
  15. e.TimeUsedCPU = 0;
  16. strcpy(e.Name, "A");
  17. e.NeedRunningTime = 1;
  18. e.Priority = GetPriority(&e, PR);
  19. if(PR == SPF) e.ArrivalTime = 0;
  20. GetProcess(*pPCBdata,e);
  21. e.ArrivalTime = 1;
  22. e.ProcessState = Ready;
  23. e.TimeUsedCPU = 0;
  24. strcpy(e.Name, "B");
  25. e.NeedRunningTime = 100;
  26. e.Priority = GetPriority(&e, PR);
  27. if(PR == SPF) e.ArrivalTime = 0;
  28. GetProcess(*pPCBdata,e);
  29. e.ArrivalTime = 2;
  30. e.ProcessState = Ready;
  31. e.TimeUsedCPU = 0;
  32. strcpy(e.Name, "C");
  33. e.NeedRunningTime = 1;
  34. e.Priority = GetPriority(&e, PR);
  35. if(PR == SPF) e.ArrivalTime = 0;
  36. GetProcess(*pPCBdata,e);
  37. e.ArrivalTime = 3;
  38. e.ProcessState = Ready;
  39. e.TimeUsedCPU = 0;
  40. strcpy(e.Name, "D");
  41. e.NeedRunningTime = 100;
  42. e.Priority = GetPriority(&e, PR);
  43. if(PR == SPF) e.ArrivalTime = 0;
  44. GetProcess(*pPCBdata,e);
  45. }
  46. //void InputData1(LinkList * pPCBdata, PriorityRule PR)
  47. //{
  48. // ElemType e = {{0},-1,-1,-1,-1,-1,0,Ready};
  49. // e.ArrivalTime = 0;
  50. // e.ProcessState = Ready;
  51. // e.TimeUsedCPU = 0;
  52. // strcpy(e.Name,"A");
  53. // e.NeedRunningTime = 4;
  54. // e.Priority = GetPriority(&e, PR);
  55. // if(PR == SPF) e.ArrivalTime = 0;
  56. // GetProcess(*pPCBdata,e);
  57. //
  58. // e.ArrivalTime = 1;
  59. // e.ProcessState = Ready;
  60. // e.TimeUsedCPU = 0;
  61. // strcpy(e.Name,"B");
  62. // e.NeedRunningTime = 3;
  63. // e.Priority = GetPriority(&e, PR);
  64. // if(PR == SPF) e.ArrivalTime = 0;
  65. // GetProcess(*pPCBdata,e);
  66. //
  67. // e.ArrivalTime = 2;
  68. // e.ProcessState = Ready;
  69. // e.TimeUsedCPU = 0;
  70. // strcpy(e.Name,"C");
  71. // e.NeedRunningTime = 5;
  72. // e.Priority = GetPriority(&e, PR);
  73. // if(PR == SPF) e.ArrivalTime = 0;
  74. // GetProcess(*pPCBdata,e);
  75. //
  76. // e.ArrivalTime = 3;
  77. // e.ProcessState = Ready;
  78. // e.TimeUsedCPU = 0;
  79. // strcpy(e.Name,"D");
  80. // e.NeedRunningTime = 2;
  81. // e.Priority = GetPriority(&e, PR);
  82. // if(PR == SPF) e.ArrivalTime = 0;
  83. // GetProcess(*pPCBdata,e);
  84. //
  85. // e.ArrivalTime = 4;
  86. // e.ProcessState = Ready;
  87. // e.TimeUsedCPU = 0;
  88. // strcpy(e.Name,"E");
  89. // e.NeedRunningTime = 4;
  90. // e.Priority = GetPriority(&e, PR);
  91. // if(PR == SPF) e.ArrivalTime = 0;
  92. // GetProcess(*pPCBdata,e);
  93. //}
  94. int main(void)
  95. {
  96. LinkList PCBQueue; //InitPCBdata里面存放PCB初始数据
  97. ElemType e = {{ 0}, -1, -1, -1, -1, -1, 0,Ready};
  98. ElemType *pcb = NULL;
  99. PriorityRule PR;
  100. PR = FCFS; // SPF or FCFS
  101. //*********** 初始化就绪队列 *************//
  102. Init(&PCBQueue);
  103. InputData(&PCBQueue, PR);
  104. printf( "初始数据如下:\n");
  105. PrintProQueue(PCBQueue, pcb);
  106. //*********** 进程根据优先级上CPU *************//
  107. printf( "\n进程运行信息如下:\n");
  108. while (OutProsess(PCBQueue, &e))
  109. {
  110. //一次性运行完毕
  111. while(e.TimeUsedCPU < e.NeedRunningTime) //上完CPU的进程是否完毕
  112. {
  113. CPURunPro(PCBQueue, &e); //上CPU
  114. ++CPUUsedTime; //CPU时间增加
  115. }
  116. //*********** 当进程执行完毕时打印输出 *************//
  117. e.FinishTime = CPUUsedTime;
  118. PrintProResult(&e);
  119. }
  120. getchar();
  121. return 0;
  122. }

二、模拟银行家算法 

介绍

data.h


  
  1. #ifndef _Data_h_
  2. #define _Data_h_
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #define ElemType PCB
  7. #define Status int
  8. #define true 1
  9. #define false 0
  10. #define OK 1
  11. #define ERROR 0
  12. #define RESOURCE_NUM 3
  13. #define MAX_RESOURCE_A_NUM 10
  14. #define MAX_RESOURCE_B_NUM 5
  15. #define MAX_RESOURCE_C_NUM 7
  16. #define NAME_MAXSIZE 20
  17. #define PCB_Num 5
  18. typedef struct{
  19. int MaxNum[RESOURCE_NUM]; //需要每项资源个数
  20. int AllocationNum[RESOURCE_NUM]; //已占用每项资源个数
  21. int NeedNum[RESOURCE_NUM]; //还需要的每项资源个数
  22. }ResourceList;
  23. typedef struct
  24. {
  25. char Name[NAME_MAXSIZE]; //进程名
  26. ResourceList resList; //资源清单
  27. }PCB;
  28. typedef struct Node
  29. {
  30. ElemType data;
  31. struct Node * Next;
  32. }LNode,*LinkList;
  33. #endif

chainlist.h


  
  1. #ifndef _ChainList_h_
  2. #define _ChainList_h_
  3. #include "Data.h"
  4. Status Init(LinkList *L);
  5. void Assignment(ElemType *e1, ElemType e2);
  6. Status ListInsert_L(LinkList L,ElemType e);
  7. #endif

实现

ProPCB.h


  
  1. #ifndef _ProPCB_h_
  2. #define _ProPCB_h_
  3. #include "ChainList.h"
  4. #include <string.h>
  5. //上队列
  6. Status GetProcess(LinkList Q,ElemType e);
  7. //银行家算法
  8. Status BankerAlgorithm(int *Allocation, int *Request,int i, int *Need, int *Available);
  9. //安全性检测算法
  10. Status SecurityCheck(int *Allocation,int *Need, int *Available);
  11. //分配资源
  12. Status AllocateResource(LinkList PCBdata , int pos , int *Request);
  13. //获取资源矩阵
  14. void GetMatrixData(LinkList PCBdata,int *Max,int *Allocation,int *Need,int *Available);
  15. //打印进程资源信息
  16. void PrintProQueue(LinkList L, int *A);
  17. //得到指定PCB名的位置
  18. void GetPos(LinkList L, char *name, int len, int *pos);
  19. //对当前的请求进行预分配
  20. void PreGrant(int* Allocation, int *Request,int pos,int *Need, int *Available);
  21. //正式分配算法
  22. void GrantSource(LinkList L, int *Request, int pos, int *Available);
  23. #endif

chainlist.c


  
  1. #include "ChainList.h"
  2. extern int CPUUsedTime;
  3. Status Init(LinkList *L)
  4. {
  5. *L = (LinkList) malloc( sizeof(LNode));
  6. strcpy((*L)->data.Name, "");
  7. (*L)->Next = NULL;
  8. return OK;
  9. }
  10. void Assignment(ElemType *e1, ElemType e2)
  11. {
  12. int i = 0;
  13. strcpy(e1->Name,e2.Name);
  14. for(i = 0; i < RESOURCE_NUM; ++i)
  15. {
  16. e1->resList.AllocationNum[i] = e2.resList.AllocationNum[i];
  17. e1->resList.MaxNum[i] = e2.resList.MaxNum[i];
  18. e1->resList.NeedNum[i] = e2.resList.NeedNum[i];
  19. }
  20. }
  21. Status ListInsert_L(LinkList L,ElemType e) //这样修改应该不对 p = *L出错
  22. {
  23. LinkList p = L, s;
  24. while (p->Next)
  25. p = p->Next;
  26. s = (LinkList) malloc( sizeof(LNode));
  27. Assignment(&s->data, e);
  28. s->Next = p->Next;
  29. p->Next = s;
  30. return OK;
  31. }

ProPCB.c


  
  1. #include "ProPCB.h"
  2. Status GetProcess(LinkList Q,ElemType e)
  3. {
  4. return ListInsert_L(Q, e);
  5. }
  6. Status AllocateResource(LinkList PCBdata , int pos , int *Request)
  7. {
  8. int i = 1;
  9. LNode *p = PCBdata->Next;
  10. while (p && i < pos)
  11. {
  12. p = p->Next;
  13. ++i;
  14. }
  15. if(!p || i > pos)
  16. return ERROR;
  17. for (i = 0; i < RESOURCE_NUM; ++i)
  18. {
  19. p->data.resList.AllocationNum[i] += Request[i];
  20. p->data.resList.NeedNum[i] -= Request[i];
  21. }
  22. return OK;
  23. }
  24. void GetMatrixData(LinkList PCBdata,int *Max,int *Allocation,int *Need,int *Available)
  25. {
  26. LNode *p;
  27. int i, j, c = RESOURCE_NUM;
  28. Available[ 0] = Available[ 1] = Available[ 2] = 0;
  29. for(p = PCBdata->Next, i = 0; p; p = p->Next, ++i)
  30. {
  31. for(j = 0; j < RESOURCE_NUM; ++j)
  32. {
  33. Max[i * c + j] = p->data.resList.MaxNum[j];
  34. Allocation[i * c + j] = p->data.resList.AllocationNum[j];
  35. Need[i * c + j] = p->data.resList.NeedNum[j];
  36. }
  37. Available[ 0] += Allocation[i * c + 0];
  38. Available[ 1] += Allocation[i * c + 1];
  39. Available[ 2] += Allocation[i * c + 2];
  40. }
  41. Available[ 0] = MAX_RESOURCE_A_NUM - Available[ 0];
  42. Available[ 1] = MAX_RESOURCE_B_NUM - Available[ 1];
  43. Available[ 2] = MAX_RESOURCE_C_NUM - Available[ 2];
  44. }
  45. void PrintProQueue(LinkList L,int *available)
  46. {
  47. int i = 0;
  48. L = L->Next;
  49. printf( " -------------------------------------------------------------\n");
  50. printf( "|进程名 | Max | Allocation | Need | Available |\n");
  51. printf( "| | A B C | A B C | A B C | A B C |\n");
  52. while(L)
  53. {
  54. printf( "| %s | %d %d %d | %d %d %d | %d %d %d | %d %d %d |\n",
  55. L->data.Name, L->data.resList.MaxNum[ 0], L->data.resList.MaxNum[ 1], L->data.resList.MaxNum[ 2],
  56. L->data.resList.AllocationNum[ 0],L->data.resList.AllocationNum[ 1],L->data.resList.AllocationNum[ 2],
  57. L->data.resList.NeedNum[ 0],L->data.resList.NeedNum[ 1],L->data.resList.NeedNum[ 2],
  58. available[ 0], available[ 1], available[ 2]);
  59. L = L->Next;
  60. }
  61. printf( " -------------------------------------------------------------\n");
  62. }
  63. //安全性检测算法
  64. Status SecurityCheck(int *Allocation,int *Need, int *Available)
  65. {
  66. / 以下补充 //
  67. int work[RESOURCE_NUM];
  68. int Finish[PCB_Num];
  69. int k, i, j, t, f;
  70. int flag;
  71. //初始化工作向量和标记数组
  72. memcpy(work, Available, sizeof work);
  73. memset(Finish, 0, sizeof Finish);
  74. //最多检测PCB_Num次
  75. for(k = 0; k < PCB_Num; ++k){
  76. flag = 0;
  77. for(i = 0; i < PCB_Num; ++i){
  78. //已经被访问
  79. if(Finish[i]){
  80. continue;
  81. }
  82. //检测是否所有资源都能被分配
  83. for(j = 0; j < RESOURCE_NUM; ++j){
  84. if(!(Need[i * 3 + j] <= work[j])){
  85. break;
  86. }
  87. }
  88. //可以满足,回收
  89. if(j == RESOURCE_NUM){
  90. for(t = 0; t < RESOURCE_NUM; ++t){
  91. work[t] += Allocation[i * 3 + t];
  92. }
  93. Finish[i] = 1;
  94. flag = 1;
  95. break;
  96. }
  97. }
  98. //为进行分配,跳出循环
  99. if(!flag){
  100. break;
  101. }
  102. }
  103. for(f = 0; f < PCB_Num; ++f){
  104. //只要有一个进程不满足,跳出循环
  105. if(!Finish[f]){
  106. return ERROR;
  107. }
  108. }
  109. return OK;
  110. }
  111. //银行家算法
  112. Status BankerAlgorithm(int* Allocation, int *Request,int pos,int *Need, int *Available)
  113. {
  114. / 以下补充 //
  115. int i;
  116. //检查请求的是否大于需要的
  117. for(i = 0; i < RESOURCE_NUM; ++i){
  118. if(Request[i] > Need[pos* 3 + i]){
  119. return ERROR;
  120. }
  121. }
  122. //检查请求的是否大于可分配的
  123. for(i = 0; i < RESOURCE_NUM; ++i){
  124. if(Request[i] > Available[i]){
  125. return ERROR;
  126. }
  127. }
  128. //进行预分配
  129. PreGrant(Allocation, Request, pos, Need, Available);
  130. //进行安全性检测
  131. if(!SecurityCheck(Allocation, Need, Available)){
  132. return ERROR;
  133. }
  134. return OK;
  135. }
  136. //根据PCB的名字得到该PCB在链表中的位置
  137. void GetPos(LinkList L, char *name, int len, int *pos)
  138. {
  139. LinkList p = L->Next;
  140. char PcbName[NAME_MAXSIZE];
  141. memcpy(PcbName, name, (len + 1) * sizeof( char));
  142. (*pos) = 0;
  143. while(p){
  144. if( strcmp(p->data.Name, PcbName)){
  145. (*pos)++;
  146. p = p->Next;
  147. } else {
  148. break;
  149. }
  150. }
  151. }
  152. //预分配算法
  153. void PreGrant(int* Allocation, int *Request,int pos,int *Need, int *Available){
  154. int i;
  155. //1. Need减去请求的
  156. for(i = 0; i < RESOURCE_NUM; ++i){
  157. Need[pos* 3 + i] -= Request[i];
  158. }
  159. //2. Available减去请求的
  160. for(i = 0; i < RESOURCE_NUM; ++i){
  161. Available[i] -= Request[i];
  162. }
  163. //3. Allocation加上请求的
  164. for(i = 0; i < RESOURCE_NUM; ++i){
  165. Allocation[pos* 3 + i] += Request[i];
  166. }
  167. }
  168. /**
  169. * 1.首先对请求资源的进程进行分配资源
  170. * 2.如果给该进程分配资源之后,该进程所需的资源等于已经得到的资源,那么对其拥有的资源进行回收
  171. */
  172. //正式分配算法,pos从0开始标记
  173. void GrantSource(LinkList L, int *Request, int pos, int *Available){
  174. LinkList p = L->Next;
  175. int tag = 0;
  176. int i;
  177. int flag = 0;
  178. if(tag < pos && NULL != p){
  179. p = p->Next;
  180. tag++;
  181. }
  182. if(p){
  183. //已获得的加上请求的
  184. for(i = 0; i < RESOURCE_NUM; ++i){
  185. p->data.resList.AllocationNum[i] += Request[i];
  186. }
  187. //还需要的减去请求的
  188. for(i = 0; i < RESOURCE_NUM; ++i){
  189. p->data.resList.NeedNum[i] -= Request[i];
  190. }
  191. //可利用的减去请求的
  192. for(i = 0; i < RESOURCE_NUM; ++i){
  193. Available[i] -= Request[i];
  194. }
  195. //如果进行分配之后该进程最大所需资源数目等于已获得的资源数目,则对资源进行回收
  196. flag = 0;
  197. for(i = 0; i < RESOURCE_NUM; ++i){
  198. if(p->data.resList.AllocationNum[i] != p->data.resList.MaxNum[i]){
  199. flag = 1;
  200. break;
  201. }
  202. }
  203. if(!flag){
  204. for(i = 0; i < RESOURCE_NUM; ++i){
  205. Available[i] += p->data.resList.AllocationNum[i];
  206. }
  207. }
  208. }
  209. }

main


  
  1. #include "ProPCB.h"
  2. void InputData(LinkList * pPCBdata)
  3. {
  4. ElemType e = {{ 0},{{ 0},{ 0},{ 0}}};
  5. strcpy(e.Name, "P0");
  6. e.resList.MaxNum[ 0] = 7; e.resList.MaxNum[ 1] = 5; e.resList.MaxNum[ 2] = 3;
  7. e.resList.AllocationNum[ 0] = 0;
  8. e.resList.AllocationNum[ 1] = 1;
  9. e.resList.AllocationNum[ 2] = 0;
  10. e.resList.NeedNum[ 0] = 7; e.resList.NeedNum[ 1] = 4; e.resList.NeedNum[ 2] = 3;
  11. GetProcess(*pPCBdata,e);
  12. strcpy(e.Name, "P1");
  13. e.resList.MaxNum[ 0] = 3; e.resList.MaxNum[ 1] = 2; e.resList.MaxNum[ 2] = 2;
  14. e.resList.AllocationNum[ 0] = 2;
  15. e.resList.AllocationNum[ 1] = 0;
  16. e.resList.AllocationNum[ 2] = 0;
  17. e.resList.NeedNum[ 0] = 1; e.resList.NeedNum[ 1] = 2; e.resList.NeedNum[ 2] = 2;
  18. GetProcess(*pPCBdata,e);
  19. strcpy(e.Name, "P2");
  20. e.resList.MaxNum[ 0] = 9; e.resList.MaxNum[ 1] = 0; e.resList.MaxNum[ 2] = 2;
  21. e.resList.AllocationNum[ 0] = 3;
  22. e.resList.AllocationNum[ 1] = 0;
  23. e.resList.AllocationNum[ 2] = 2;
  24. e.resList.NeedNum[ 0] = 6; e.resList.NeedNum[ 1] = 0; e.resList.NeedNum[ 2] = 0;
  25. GetProcess(*pPCBdata,e);
  26. strcpy(e.Name, "P3");
  27. e.resList.MaxNum[ 0] = 2; e.resList.MaxNum[ 1] = 2; e.resList.MaxNum[ 2] = 2;
  28. e.resList.AllocationNum[ 0] = 2;
  29. e.resList.AllocationNum[ 1] = 1;
  30. e.resList.AllocationNum[ 2] = 1;
  31. e.resList.NeedNum[ 0] = 0; e.resList.NeedNum[ 1] = 1; e.resList.NeedNum[ 2] = 1;
  32. GetProcess(*pPCBdata,e);
  33. strcpy(e.Name, "P4");
  34. e.resList.MaxNum[ 0] = 4; e.resList.MaxNum[ 1] = 3; e.resList.MaxNum[ 2] = 3;
  35. e.resList.AllocationNum[ 0] = 0;
  36. e.resList.AllocationNum[ 1] = 0;
  37. e.resList.AllocationNum[ 2] = 2;
  38. e.resList.NeedNum[ 0] = 4; e.resList.NeedNum[ 1] = 3; e.resList.NeedNum[ 2] = 1;
  39. GetProcess(*pPCBdata,e);
  40. }
  41. int main(void)
  42. {
  43. LinkList PCBdata; //PCBdata里面存放原始数据
  44. ElemType e = {{ 0},{{ 0},{ 0},{ 0}}};
  45. char PcbName[NAME_MAXSIZE], chioce;
  46. int Max[PCB_Num][RESOURCE_NUM] = { 0}, Allocation[PCB_Num][RESOURCE_NUM] = { 0};
  47. int Need[PCB_Num][RESOURCE_NUM] = { 0}, Available[RESOURCE_NUM] = { 0};
  48. int Request[RESOURCE_NUM] = { 0}, pos = 0;
  49. LNode *p = NULL;
  50. int i;
  51. / 以下补充 //
  52. //初始化就绪队列
  53. Init(&PCBdata);
  54. //数据输入
  55. InputData(&PCBdata);
  56. while( 1){
  57. //获取所有PCB中的资源信息
  58. GetMatrixData(PCBdata, *Max, *Allocation, *Need, Available);
  59. //打印当前系统的状态
  60. PrintProQueue(PCBdata, Available);
  61. //接受请求
  62. printf( "请输入申请资源的进程名,资源A,资源B,资源C申请量(空格隔开):");
  63. scanf( "%s", PcbName);
  64. for(i = 0; i < RESOURCE_NUM; ++i){
  65. scanf( "%d", &Request[i]);
  66. }
  67. //获取相应的PCB在链表中的位置
  68. GetPos(PCBdata, PcbName, strlen(PcbName), &pos);
  69. //跑银行家算法,根据返回值的状态判断是否安全,
  70. //如果安全,进行正式分配,否则仅仅打印不安全信息
  71. if(BankerAlgorithm(*Allocation, Request, pos, *Need, Available)){
  72. //正式分配资源
  73. GrantSource(PCBdata, Request, pos, Available);
  74. //分配完成后,打印资源的信息
  75. GetMatrixData(PCBdata, *Max, *Allocation, *Need, Available);
  76. PrintProQueue(PCBdata, Available);
  77. printf( "请安任意键继续. . . ");
  78. getchar();
  79. getchar();
  80. } else {
  81. printf( "不安全,不可分配!\n");
  82. }
  83. }
  84. return 0;
  85. }

三、模拟固定分区分配 

介绍

data.h


  
  1. #ifndef _Data_h_
  2. #define _Data_h_
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #define LIST_INIT_SIZE 10
  7. #define LISTINCREMENT 2
  8. #define true 1
  9. #define false 0
  10. #define PCBType PCB
  11. #define Status int
  12. #define OK 1
  13. #define ERROR 0
  14. #define NAME_MAXSIZE 20
  15. #define PCB_Num 5
  16. #define LIST_INITSIZE 10
  17. #define PartiType PartitionInfo
  18. #define TotalMemory 512 //KB
  19. typedef enum
  20. {
  21. Unallocated, Allocated
  22. }DistributState, PartitionSt;
  23. typedef enum
  24. {
  25. FirstPriority, BestAdapt
  26. }AllocatStrategy;
  27. typedef struct
  28. {
  29. char Name[NAME_MAXSIZE]; //进程名
  30. int MemorySize; //内存的大小
  31. int StartAddress; //内存起始地址
  32. DistributState DistbutSt; //分配状态
  33. }PCB;
  34. typedef struct Node
  35. {
  36. PCBType data;
  37. struct Node * Next;
  38. }LNode, *LinkList, *PCBList; //
  39. typedef struct {
  40. //分区号用数组下标代替
  41. int PartitionSize;
  42. int PartStartAddr;
  43. char Name[NAME_MAXSIZE]; //若为空,则分区空闲
  44. }PartitionInfo;
  45. typedef struct
  46. {
  47. PartiType *elem;
  48. int listsize; //表容量
  49. int length; //元素个数
  50. }SqList, PartTable; //分区表
  51. #endif

list.h


  
  1. #ifndef _List_h_
  2. #define _List_h_
  3. #include "Data.h"
  4. //******* 链表 *******//
  5. Status InitLinkList(LinkList *L);
  6. void PCBAssign(PCBType *e1, PCBType e2);
  7. Status GetElemt_L(LinkList L,int i,PCBType *e);
  8. Status ListInsert_L(LinkList L,PCBType e);
  9. Status ListDelete_L(LinkList L,int i,PCBType *e);
  10. //****** 动态顺序表 ******//
  11. void PartiAssign(PartiType *e1, PartiType e2);
  12. Status InitList_Sq(SqList *L);
  13. Status ListInsert_Sq(SqList *L,int i,PartiType e);
  14. Status ListDelete_Sq(SqList *L,int i,PartiType *e);
  15. #endif

 


  
  1. #ifndef _MemoryManage_h_
  2. #define _MemoryManage_h_
  3. #include "List.h"
  4. //***** PCB链表操作 *****//
  5. Status InsertProcess(LinkList Q,PCBType e);
  6. Status DeleteProsess(LinkList Q,int i,PCBType *e);
  7. //***** 分区表操作 *****//
  8. Status InsertTable(SqList *L, int i, PartiType e);
  9. Status DeleteTable(SqList *L, int i, PartiType *e);
  10. int SelectPart(PCB* pPCB, SqList *pPartTable);
  11. int MallocMemory(PCB *pe, SqList *pPartTable, int pos);
  12. void SearchSpace(PCBList PCBdata, SqList partTable);
  13. void FreeMemory(int pos, SqList *pPartTable);
  14. void InitAllocation(PCBList PCBdata, PartTable partTable);
  15. void PrintProQueue(LinkList L);
  16. void PrintPartTable(PartTable L);
  17. #endif

实现

list.c


  
  1. #include "List.h"
  2. Status InitLinkList(LinkList *L)
  3. {
  4. *L = (LinkList) malloc( sizeof(LNode));
  5. strcpy((*L)->data.Name, "");
  6. (*L)->Next = NULL;
  7. return OK;
  8. }
  9. void PCBAssign(PCBType *e1, PCBType e2)
  10. {
  11. strcpy(e1->Name,e2.Name);
  12. e1->DistbutSt = e2.DistbutSt;
  13. e1->MemorySize = e2.MemorySize;
  14. e1->StartAddress = e2.StartAddress;
  15. }
  16. Status GetElemt_L(LinkList L,int i,PCBType *e)
  17. {
  18. LinkList p = L->Next; //指向第j个结点
  19. int j = 1; //从第一个开始往后找
  20. while ( p && j < i ) //p不为空且j < i
  21. {
  22. p = p->Next;
  23. ++j;
  24. } //p为空,说明链表循环结束,也没有到第i个结点 j==i
  25. if (!p || j > i) //因为此处对i 没有做判断 如果 i==0 或 负数 条件成立
  26. //对于 i == j == 1 的情况则不用循环正好 返回
  27. {
  28. return ERROR;
  29. }
  30. *e = p->data; //通过寻址改变了 该地址内存中元素的值
  31. return OK;
  32. }
  33. //链表中按照优先级:从大到小排序插入
  34. Status ListInsert_L(LinkList L,PCBType e) //这样修改应该不对 p = *L出错
  35. {
  36. LinkList p = L, s;
  37. while (p->Next)
  38. p = p->Next;
  39. s = (LinkList) malloc( sizeof(LNode));
  40. PCBAssign(&s->data, e);
  41. s->Next = p->Next;
  42. p->Next = s;
  43. return OK;
  44. }
  45. //链表中头部删除
  46. Status ListDelete_L(LinkList L,int i,PCBType *e)
  47. {
  48. LinkList p = L, q;
  49. int j = 0;
  50. while (p->Next && j < i -1)
  51. {
  52. p = p->Next; ++j;
  53. }
  54. if(!p->Next || j > i - 1)
  55. return ERROR;
  56. q = p->Next;
  57. p->Next = q->Next;
  58. PCBAssign(e, q->data);
  59. free(q);
  60. return OK;
  61. }
  62. // 初始化 ///
  63. void PartiAssign(PartiType *e1, PartiType e2)
  64. {
  65. e1->PartitionSize = e2.PartitionSize;
  66. e1->PartStartAddr = e2.PartStartAddr;
  67. strcpy(e1->Name, e2.Name);
  68. }
  69. Status InitList_Sq(SqList *L)
  70. {
  71. //构造一个空的线性表L
  72. L->elem = (PartiType *) malloc((LIST_INIT_SIZE)* sizeof(PartiType));
  73. if(!L->elem) return ERROR; //存储分配失败
  74. L->length = 0; //空表长度为0
  75. L->listsize = LIST_INIT_SIZE; //初始存储的容量
  76. return OK;
  77. }
  78. //在顺序线性表L中第i个位置之前插入新的元素e
  79. Status ListInsert_Sq(SqList *L,int i,PartiType e)
  80. {
  81. //在顺序线性表L中第i个位置之前插入新的元素e
  82. //i的合法值为1 <= i <= ListLength_Sq(L)+1
  83. PartiType *q, *p, *newbase;
  84. if(i < 1 || i > L->length + 1 ) return ERROR; //i值不合法
  85. if(L->length >= L->listsize){ //当前存储空间已满,增加分配
  86. newbase = (PartiType *) realloc(L->elem
  87. ,(L->listsize + LISTINCREMENT)* sizeof(PartiType));
  88. if(!newbase) return ERROR; //存储分配失败
  89. L->elem = newbase; //新基址
  90. L->listsize += LISTINCREMENT; //增加存储容量
  91. }
  92. q = &(L->elem[i - 1]); //q为插入位置
  93. for(p = &(L->elem[L->length -1]);p >= q; --p)
  94. PartiAssign((p+ 1),*p); //插入位置及之后的元素右移
  95. PartiAssign(q ,e); //插入e
  96. L->length++;
  97. return OK;
  98. }
  99. //在顺序线性表L中删除第i个元素,并用e返回其值
  100. Status ListDelete_Sq(SqList *L,int i,PartiType *e)
  101. {
  102. //在顺序线性表L中删除第i个元素,并用e返回其值
  103. //i的合法值为1 <= i <= ListLength_Sq(L)
  104. PartiType *p,*q;
  105. if((i < 1) || (i > L->length))
  106. return ERROR; //i值不合法
  107. p = &(L->elem[i -1]); //p为被删除元素的位置
  108. PartiAssign(e, *p); //将被删除元素的值赋给e (待定)
  109. q = L->elem + L->length -1; //移动到表尾元素的位置
  110. for (++p;p<=q;++p)
  111. PartiAssign((p -1), *p); //被删除元素之后的元素左移
  112. L->length--;
  113. return OK;
  114. }

memoryManage.c


  
  1. #include "MemoryManage.h"
  2. //***** PCB链表操作 *****//
  3. Status InsertProcess(LinkList Q,PCBType e)
  4. {
  5. return ListInsert_L(Q, e);
  6. }
  7. Status DeleteProsess(LinkList Q,int i,PCBType *e)
  8. {
  9. return ListDelete_L(Q ,i,e);
  10. }
  11. //***** 分区表操作 *****//
  12. Status InsertTable(SqList *L, int i, PartiType e)
  13. {
  14. return ListInsert_Sq(L,i, e);
  15. }
  16. Status DeleteTable(SqList *L, int i, PartiType *e)
  17. {
  18. return ListDelete_Sq(L, i, e);
  19. }
  20. //返回第几个内存块,从1开始,若返回0,则代表错误
  21. int SelectPart(PCB* pPCB, SqList *pPartTable)
  22. {
  23. int i,Start;
  24. if(pPCB->MemorySize <= 16)
  25. Start = 0;
  26. else if(pPCB->MemorySize <= 32)
  27. Start = 1;
  28. else if(pPCB->MemorySize <= 64)
  29. Start = 2;
  30. else if(pPCB->MemorySize <= 128)
  31. Start = 3;
  32. else if(pPCB->MemorySize <= 256)
  33. Start = 4;
  34. else
  35. {
  36. printf( "内存过大,无法装入!\n");
  37. return ERROR;
  38. }
  39. for (i = Start; i < pPartTable->length; ++i)
  40. if(! strcmp(pPartTable->elem[i].Name, ""))
  41. return i + 1;
  42. return ERROR;
  43. }
  44. //i传递的是下标
  45. int MallocMemory(PCB *pe, SqList *pPartTable,int i)
  46. {
  47. /// 以下需要补充 /
  48. pe->DistbutSt = Allocated;
  49. pe->StartAddress = pPartTable->elem[i].PartStartAddr;
  50. strcpy(pPartTable->elem[i].Name, pe->Name);
  51. return OK;
  52. }
  53. /**
  54. * PCBdata:表示PCB链
  55. * partTable:分区表
  56. * 将每一个PCB取出,查找是否有合适的分区可以分配给他,如果有分配,如果没有不分配
  57. */
  58. void InitAllocation(PCBList PCBdata, PartTable partTable)
  59. {
  60. /// 以下需要补充 /
  61. PCBList L = PCBdata->Next;
  62. int pos;
  63. while(L){
  64. pos = SelectPart(&L->data, &partTable);
  65. if(pos == 0) {
  66. printf( "无法为%s进程分配空间!!!\n", L->data.Name);
  67. } else {
  68. L->data.DistbutSt = Allocated;
  69. L->data.StartAddress = partTable.elem[pos -1].PartStartAddr;
  70. strcpy(partTable.elem[pos -1].Name, L->data.Name);
  71. }
  72. L = L->Next;
  73. }
  74. //SearchSpace(PCBdata, partTable);
  75. }
  76. void FreeMemory(int pos, SqList *pPartTable)
  77. {
  78. /// 以下需要补充 /
  79. strcpy(pPartTable->elem[pos].Name, "");
  80. }
  81. void SearchSpace(PCBList PCBdata, SqList partTable)
  82. {
  83. int pos;
  84. LNode *p;
  85. p = PCBdata->Next;
  86. while (p)
  87. {
  88. if(p->data.DistbutSt == Unallocated)
  89. {
  90. pos = SelectPart(&(p->data), &partTable); //从1开始
  91. if(pos)
  92. {
  93. MallocMemory(&(p->data), &partTable, pos - 1);
  94. break;
  95. }
  96. }
  97. p = p->Next;
  98. }
  99. }
  100. void PrintProQueue(LinkList L)
  101. {
  102. int i = 0;
  103. L = L->Next;
  104. printf( " ----------------------------------------\n");
  105. printf( "|进程名 | 起始位置 | 申请大小 | 是否分配 |\n");
  106. while(L)
  107. {
  108. printf( "| %s | %4d | %4d | %4s |\n",
  109. L->data.Name, L->data.StartAddress, L->data.MemorySize, L->data.DistbutSt == Allocated? "是" : "否");
  110. L = L->Next;
  111. }
  112. printf( " ----------------------------------------\n");
  113. }
  114. void PrintPartTable(PartTable L)
  115. {
  116. int i = 0, j = 0;
  117. printf( " ----------------------------------------\n");
  118. printf( "|分区号 | 起始位置 | 分区大小 | 是否分配 |\n");
  119. for (i = 0; i < L.length; ++i)
  120. printf( "| %2d | %4d | %4d | %4s |\n",
  121. i + 1 , L.elem[i].PartStartAddr, L.elem[i].PartitionSize , strcmp(L.elem[i].Name, "") ? L.elem[i].Name : "否");
  122. printf( " ----------------------------------------\n");
  123. }

main


  
  1. #include "MemoryManage.h"
  2. /*实验06 固定分区分配
  3. * 分配策略:
  4. * ①离队首最近,能够装入该分区的进程;
  5. * ②搜索能够装入该分区最大的进程。
  6. */
  7. void InputPCBData(PCBList * pPCBdata)
  8. {
  9. PCBType e = {{ 0}, 0, 0, Unallocated};
  10. strcpy(e.Name, "P1");
  11. e.MemorySize = 16;
  12. InsertProcess(*pPCBdata,e);
  13. strcpy(e.Name, "P2");
  14. e.MemorySize = 32;
  15. InsertProcess(*pPCBdata,e);
  16. strcpy(e.Name, "P3");
  17. e.MemorySize = 48;
  18. InsertProcess(*pPCBdata,e);
  19. strcpy(e.Name, "P4");
  20. e.MemorySize = 96;
  21. InsertProcess(*pPCBdata,e);
  22. strcpy(e.Name, "P5");
  23. e.MemorySize = 100;
  24. InsertProcess(*pPCBdata,e);
  25. }
  26. void SetFixedZone(PartTable * pPartdata)
  27. {
  28. PartiType se = { 0, 0, Unallocated };
  29. se.PartStartAddr = 16;
  30. se.PartitionSize = 16;
  31. InsertTable(pPartdata, 1, se);
  32. se.PartStartAddr = 32;
  33. se.PartitionSize = 32;
  34. InsertTable(pPartdata, 2, se);
  35. se.PartStartAddr = 64;
  36. se.PartitionSize = 64;
  37. InsertTable(pPartdata, 3, se);
  38. se.PartStartAddr = 128;
  39. se.PartitionSize = 128;
  40. InsertTable(pPartdata, 4, se);
  41. se.PartStartAddr = 256;
  42. se.PartitionSize = 256;
  43. InsertTable(pPartdata, 5, se);
  44. }
  45. //0 - 15Kb 操作系统占用 总大小512KB
  46. int main(void)
  47. {
  48. PCBList PCBdata; //PCBdata里面存放原始PCB数据
  49. PartTable partTable; //分区表
  50. char PcbName[NAME_MAXSIZE] = { 0}, choice;
  51. PCBType PCBe = {{ 0}, 0, 0, Unallocated};
  52. PartiType Parte = { 0, 0};
  53. PCBType tmp;
  54. PCBType *pcb = NULL;
  55. LNode *p;
  56. PCBList pl = NULL;
  57. int tpos = 0;
  58. int startAddress;
  59. int i, size, pos, j;
  60. InitList_Sq(&partTable);
  61. SetFixedZone(&partTable);
  62. InitLinkList(&PCBdata);
  63. InputPCBData(&PCBdata);
  64. InitAllocation(PCBdata, partTable);
  65. PrintProQueue(PCBdata);
  66. PrintPartTable(partTable);
  67. while( true)
  68. {
  69. system( "cls");
  70. PrintProQueue(PCBdata);
  71. PrintPartTable(partTable);
  72. printf( " ================================================\n");
  73. printf( "| 1.结 束 进 程 |\n");
  74. printf( "| 2.添 加 进 程 |\n");
  75. printf( "| 3.退 出 系 统 |\n");
  76. printf( " ================================================\n");
  77. printf( "请选择:");
  78. fflush( stdin);
  79. scanf( "%d",&choice);
  80. //printf("haha");
  81. switch (choice)
  82. {
  83. /// 以下需要补充 /
  84. case 1:
  85. printf( "要结束的进程名:");
  86. scanf( "%s", PcbName);
  87. //找到指定进程的位置,
  88. pl = PCBdata->Next;
  89. startAddress = -1;
  90. tpos = 0;
  91. while(pl){
  92. tpos++;
  93. if(! strcmp(pl->data.Name, PcbName) && pl->data.DistbutSt == Allocated){
  94. startAddress = pl->data.StartAddress;
  95. break;
  96. }
  97. pl = pl->Next;
  98. }
  99. if(startAddress == -1){
  100. printf( "进程不存在!!!\n");
  101. break;
  102. }
  103. //删除进程
  104. DeleteProsess(PCBdata, tpos, &tmp);
  105. //根据起始地址找到要回收的分区
  106. for(j = 0; j < partTable.length; ++j){
  107. if(partTable.elem[j].PartStartAddr == startAddress){
  108. tpos = j;
  109. break;
  110. }
  111. }
  112. //回收内存
  113. FreeMemory(tpos, &partTable);
  114. //重新检查是否可以为其他进程分配
  115. SearchSpace(PCBdata, partTable);
  116. break;
  117. case 2:
  118. printf( "请输入添加的进程名和所占分区的大小:");
  119. scanf( "%s %d", PcbName, &size);
  120. strcpy(PCBe.Name, PcbName);
  121. PCBe.MemorySize = size;
  122. PCBe.DistbutSt = Unallocated;
  123. PCBe.StartAddress = 0;
  124. InsertProcess(PCBdata, PCBe);
  125. SearchSpace(PCBdata, partTable);
  126. break;
  127. case 3:
  128. exit( 0);
  129. break;
  130. }
  131. PrintProQueue(PCBdata);
  132. PrintPartTable(partTable);
  133. system( "pause");
  134. }
  135. return 0;
  136. }

四、模拟基本分页存储

介绍

data.h


  
  1. #ifndef _Data_h_
  2. #define _Data_h_
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <math.h>
  7. #define LIST_INIT_SIZE 10
  8. #define LISTINCREMENT 2
  9. #define true 1
  10. #define false 0
  11. #define PCBType PCB
  12. #define Status int
  13. #define OK 1
  14. #define ERROR 0
  15. #define NAME_MAXSIZE 20
  16. #define PCB_Num 5
  17. #define LIST_INITSIZE 10
  18. #define PartiType PartitionInfo
  19. #define BlockNumType PageData //分页信息
  20. #define TotalMemory 512 //KB
  21. #define PageSize 16 //通常为1 ~ 8KB //进程申请内存的大小[16, 256]KB 256 / 8 = 32页
  22. typedef enum
  23. {
  24. Unallocated, Allocated
  25. }DistributState, PartitionSt;
  26. typedef struct {
  27. //分区号用数组下标代替
  28. int PartStartAddr;
  29. char Name[NAME_MAXSIZE]; //若为空,则分区空闲
  30. }PartitionInfo;
  31. typedef struct
  32. {
  33. PartitionInfo *elem;
  34. int listsize; //表容量
  35. int length; //元素个数
  36. }SqList_f, PartTable; //分区使用说明表
  37. typedef struct {
  38. int BlockNum; //块号
  39. DistributState DistbutSt; //分配状态
  40. }PageData;
  41. typedef struct
  42. {
  43. PageData *elem;
  44. int listsize;
  45. int length;
  46. }SqList_y, PageTable; //页表
  47. typedef struct
  48. {
  49. char Name[NAME_MAXSIZE]; //进程名
  50. int MemorySize; //内存的大小
  51. PageTable *pPagetable; //页表指针
  52. }PCB;
  53. typedef struct Node
  54. {
  55. PCBType data;
  56. struct Node * Next;
  57. }LNode, *LinkList, *PCBList;
  58. #endif

list.h


  
  1. #ifndef _List_h_
  2. #define _List_h_
  3. #include "Data.h"
  4. //******* 链表 *******//
  5. Status InitLinkList(LinkList *L);
  6. void PCBAssign(PCBType *e1, PCBType e2);
  7. Status GetElemt_L(LinkList L,int i,PCBType *e);
  8. Status ListInsert_L(LinkList L,PCBType e);
  9. Status ListDelete_L(LinkList L,int i,PCBType *e);
  10. //****** 分区使用说明表 ******//
  11. void PartiAssign_f(PartiType *e1, PartiType e2);
  12. Status InitList_f(SqList_f *L);
  13. Status ListInsert_f(SqList_f *L,int i,PartiType e);
  14. Status ListDelete_f(SqList_f *L,int i,PartiType *e);
  15. //****** 页表 ******//
  16. void PartiAssign_y(BlockNumType *e1, BlockNumType e2);
  17. Status InitList_y(SqList_y **L);
  18. Status ListInsert_y(SqList_y *L,int i,BlockNumType e);
  19. Status ListDelete_y(SqList_y *L,int i,BlockNumType *e);
  20. #endif

memorymanage.h


  
  1. #ifndef _MemoryManage_h_
  2. #define _MemoryManage_h_
  3. #include "List.h"
  4. //***** PCB 链 表 操 作 *****//
  5. Status InsertProcess(LinkList Q,PCBType e);
  6. Status DeleteProsess(LinkList Q,int i,PCBType *e);
  7. //***** 分 区 表 操 作 *****//
  8. //插入分区表元素
  9. Status InsertTable_f(SqList_f *L, int i, PartiType e);
  10. //删除分区表元素
  11. Status DeleteTable_f(SqList_f *L, int i, PartiType *e);
  12. //****** 页 表 操 作 ******//
  13. //插入页表元素
  14. Status InsertTable_y(SqList_y *L, int i, BlockNumType e);
  15. //删除页表元素
  16. Status DeleteTable_y(SqList_y *L, int i, BlockNumType *e);
  17. Status LoadPages(PageTable *L, int size);
  18. Status MallocMemory(PCB *pe, SqList_f *pPartTable, int *arr);
  19. Status SelectPart(PCB* pPCB, SqList_f *pPartTable,int *arr);
  20. void SearchSpace(PCBList PCBdata, SqList_f *partTable);
  21. void FreeMemory(int *arr, int len, SqList_f *pPartTable);
  22. void InitAllocation(PCBList PCBdata, PartTable *partTable);
  23. void PrintProQueue(LinkList L);
  24. void PrintPartTable(PartTable L);
  25. #endif

实现


  
  1. #include "List.h"
  2. //******* 链表 *******//
  3. Status InitLinkList(LinkList *L)
  4. {
  5. *L = (LinkList) malloc( sizeof(LNode));
  6. strcpy((*L)->data.Name, "");
  7. (*L)->Next = NULL;
  8. return OK;
  9. }
  10. void PCBAssign(PCBType *e1, PCBType e2)
  11. {
  12. strcpy(e1->Name,e2.Name);
  13. e1->MemorySize = e2.MemorySize;
  14. e1->pPagetable = e2.pPagetable;
  15. }
  16. Status GetElemt_L(LinkList L,int i,PCBType *e)
  17. {
  18. LinkList p = L->Next; //指向第j个结点
  19. int j = 1; //从第一个开始往后找
  20. while ( p && j < i ) //p不为空且j < i
  21. {
  22. p = p->Next;
  23. ++j;
  24. } //p为空,说明链表循环结束,也没有到第i个结点 j==i
  25. if (!p || j > i) //因为此处对i 没有做判断 如果 i==0 或 负数 条件成立
  26. //对于 i == j == 1 的情况则不用循环正好 返回
  27. {
  28. return ERROR;
  29. }
  30. *e = p->data; //通过寻址改变了 该地址内存中元素的值
  31. return OK;
  32. }
  33. //链表中按照优先级:从大到小排序插入
  34. Status ListInsert_L(LinkList L,PCBType e) //这样修改应该不对 p = *L出错
  35. {
  36. LinkList p = L, s;
  37. while (p->Next)
  38. p = p->Next;
  39. s = (LinkList) malloc( sizeof(LNode));
  40. PCBAssign(&s->data, e);
  41. s->Next = p->Next;
  42. p->Next = s;
  43. return OK;
  44. }
  45. Status ListDelete_L(LinkList L,int i,PCBType *e)
  46. {
  47. LinkList p = L, q;
  48. int j = 0;
  49. while (p->Next && j < i -1)
  50. {
  51. p = p->Next; ++j;
  52. }
  53. if(!p->Next || j > i - 1)
  54. return ERROR;
  55. q = p->Next;
  56. p->Next = q->Next;
  57. PCBAssign(e, q->data);
  58. free(q);
  59. return OK;
  60. }
  61. //****** 分区使用说明表 ******//
  62. void PartiAssign_f(PartiType *e1, PartiType e2)
  63. {
  64. e1->PartStartAddr = e2.PartStartAddr;
  65. strcpy(e1->Name, e2.Name);
  66. }
  67. Status InitList_f(SqList_f *L)
  68. {
  69. //构造一个空的线性表L
  70. L->elem = (PartiType *) malloc((LIST_INIT_SIZE)* sizeof(PartiType));
  71. if(!L->elem) return ERROR; //存储分配失败
  72. L->length = 0; //空表长度为0
  73. L->listsize = LIST_INIT_SIZE; //初始存储的容量
  74. return OK;
  75. }
  76. //在顺序线性表L中第i个位置之前插入新的元素e
  77. Status ListInsert_f(SqList_f *L,int i,PartiType e)
  78. {
  79. //在顺序线性表L中第i个位置之前插入新的元素e
  80. //i的合法值为1 <= i <= ListLength_Sq(L)+1
  81. PartiType *q, *p, *newbase;
  82. if(i < 1 || i > L->length + 1 ) return ERROR; //i值不合法
  83. if(L->length >= L->listsize){ //当前存储空间已满,增加分配
  84. newbase = (PartiType *) realloc(L->elem
  85. ,(L->listsize + LISTINCREMENT)* sizeof(PartiType));
  86. if(!newbase) return ERROR; //存储分配失败
  87. L->elem = newbase; //新基址
  88. L->listsize += LISTINCREMENT; //增加存储容量
  89. }
  90. q = &(L->elem[i - 1]); //q为插入位置
  91. for(p = &(L->elem[L->length -1]);p >= q; --p)
  92. PartiAssign_f((p+ 1),*p); //插入位置及之后的元素右移
  93. PartiAssign_f(q ,e); //插入e
  94. L->length++;
  95. return OK;
  96. }
  97. //在顺序线性表L中删除第i个元素,并用e返回其值
  98. Status ListDelete_f(SqList_f *L,int i,PartiType *e)
  99. {
  100. //在顺序线性表L中删除第i个元素,并用e返回其值
  101. //i的合法值为1 <= i <= ListLength_Sq(L)
  102. PartiType *p,*q;
  103. if((i < 1) || (i > L->length))
  104. return ERROR; //i值不合法
  105. p = &(L->elem[i -1]); //p为被删除元素的位置
  106. PartiAssign_f(e, *p); //将被删除元素的值赋给e (待定)
  107. q = L->elem + L->length -1; //移动到表尾元素的位置
  108. for (++p;p<=q;++p)
  109. PartiAssign_f((p -1), *p); //被删除元素之后的元素左移
  110. L->length--;
  111. return OK;
  112. }
  113. //****** 页表 ******//
  114. void PartiAssign_y(BlockNumType *e1, BlockNumType e2)
  115. {
  116. (*e1).BlockNum = e2.BlockNum;
  117. (*e1).DistbutSt = e2.DistbutSt;
  118. }
  119. Status InitList_y(SqList_y **L)
  120. {
  121. //构造一个空的线性表L
  122. (*L) = (PageTable *) malloc( sizeof(PageTable)); //不可缺少
  123. (*L)->elem = (BlockNumType *) malloc((LIST_INIT_SIZE)* sizeof(BlockNumType));
  124. if(!(*L)->elem) return ERROR; //存储分配失败
  125. (*L)->length = 0; //空表长度为0
  126. (*L)->listsize = LIST_INIT_SIZE; //初始存储的容量
  127. return OK;
  128. }
  129. //在顺序线性表L中第i个位置之前插入新的元素e
  130. Status ListInsert_y(SqList_y *L,int i,BlockNumType e)
  131. {
  132. //在顺序线性表L中第i个位置之前插入新的元素e
  133. //i的合法值为1 <= i <= ListLength_Sq(L)+1
  134. BlockNumType *q, *p, *newbase;
  135. if(i < 1 || i > L->length + 1 ) return ERROR; //i值不合法
  136. if(L->length >= L->listsize){ //当前存储空间已满,增加分配
  137. newbase = (BlockNumType *) realloc(L->elem
  138. ,(L->listsize + LISTINCREMENT)* sizeof(BlockNumType));
  139. if(!newbase) return ERROR; //存储分配失败
  140. L->elem = newbase; //新基址
  141. L->listsize += LISTINCREMENT; //增加存储容量
  142. }
  143. q = &(L->elem[i - 1]); //q为插入位置
  144. for(p = &(L->elem[L->length -1]);p >= q; --p)
  145. PartiAssign_y((p+ 1),*p); //插入位置及之后的元素右移
  146. PartiAssign_y(q ,e); //插入e
  147. L->length++;
  148. return OK;
  149. }
  150. //在顺序线性表L中删除第i个元素,并用e返回其值
  151. Status ListDelete_y(SqList_y *L,int i,BlockNumType *e)
  152. {
  153. //在顺序线性表L中删除第i个元素,并用e返回其值
  154. //i的合法值为1 <= i <= ListLength_Sq(L)
  155. BlockNumType *p,*q;
  156. if((i < 1) || (i > L->length))
  157. return ERROR; //i值不合法
  158. p = &(L->elem[i -1]); //p为被删除元素的位置
  159. PartiAssign_y(e, *p); //将被删除元素的值赋给e (待定)
  160. q = L->elem + L->length -1; //移动到表尾元素的位置
  161. for (++p;p<=q;++p)
  162. PartiAssign_y((p -1), *p); //被删除元素之后的元素左移
  163. L->length--;
  164. return OK;
  165. }

memorymanage.c


  
  1. #include "MemoryManage.h"
  2. //***** PCB链表操作 *****//
  3. Status InsertProcess(LinkList Q,PCBType e)
  4. {
  5. return ListInsert_L(Q, e);
  6. }
  7. Status DeleteProsess(LinkList Q,int i,PCBType *e)
  8. {
  9. return ListDelete_L(Q ,i,e);
  10. }
  11. //***** 分区表操作 *****//
  12. Status InsertTable_f(SqList_f *L, int i, PartiType e)
  13. {
  14. return ListInsert_f(L,i, e);
  15. }
  16. Status DeleteTable_f(SqList_f *L, int i, PartiType *e)
  17. {
  18. return ListDelete_f(L, i, e);
  19. }
  20. //***** 页表操作 *****//
  21. Status InsertTable_y(SqList_y *L, int i, BlockNumType e)
  22. {
  23. return ListInsert_y(L,i, e);
  24. }
  25. Status DeleteTable_y(SqList_y *L, int i, BlockNumType *e)
  26. {
  27. return ListDelete_y(L, i, e);
  28. }
  29. Status LoadPages(PageTable *L, int size)
  30. {
  31. int i, pageNum = ceil( size * 1.0 / PageSize) ;
  32. PageData e = { -1, Unallocated};
  33. for (i = 0; i < pageNum; i++)
  34. {
  35. if(!InsertTable_y(L, L->length + 1, e))
  36. return ERROR;
  37. }
  38. return OK;;
  39. }
  40. //若返回0,则代表错误
  41. Status SelectPart(PCB* pPCB, SqList_f *pPartTable,int *arr)
  42. {
  43. / 以下补充 /
  44. int i = 0, j = 0;
  45. while(i < pPCB->pPagetable->length && j < pPartTable->length){
  46. if(pPCB->pPagetable->elem[i].DistbutSt == Unallocated){
  47. if(! strcmp(pPartTable->elem[j].Name, "")){
  48. arr[i] = j;
  49. ++i;
  50. ++j;
  51. } else {
  52. ++j;
  53. }
  54. } else {
  55. ++i;
  56. }
  57. }
  58. if(i == pPCB->pPagetable->length){
  59. return OK;
  60. }
  61. return ERROR;
  62. }
  63. Status MallocMemory(PCB *pe, SqList_f *pPartTable, int *arr)
  64. {
  65. int i, pageNum ;
  66. 以下补充 /
  67. for(i = 0; i < pe->pPagetable->length; ++i){
  68. if(pe->pPagetable->elem[i].DistbutSt == Unallocated){
  69. pe->pPagetable->elem[i].BlockNum = arr[i];
  70. pe->pPagetable->elem[i].DistbutSt = Allocated;
  71. strcpy(pPartTable->elem[arr[i]].Name, pe->Name);
  72. }
  73. }
  74. return ERROR;
  75. }
  76. void InitAllocation(PCBList PCBdata, PartTable *pPartTable)
  77. {
  78. LNode *p;
  79. int pos, arr[ 20] = { 0};
  80. p = PCBdata->Next;
  81. while (p)
  82. {
  83. if(p->data.pPagetable->elem[ 0].DistbutSt == Unallocated)
  84. {
  85. if(SelectPart(&(p->data), pPartTable, arr))
  86. {
  87. MallocMemory(&(p->data), pPartTable, arr);
  88. }
  89. }
  90. p = p->Next;
  91. }
  92. }
  93. //该释放进程只在结束进程时用到,因此不用管进程信息
  94. void FreeMemory(int *arr, int len, SqList_f *pPartTable)
  95. {
  96. int i;
  97. 以下补充 /
  98. for(i = 0; i < len; ++i){
  99. strcpy(pPartTable->elem[arr[i]].Name, "");
  100. }
  101. }
  102. void SearchSpace(PCBList PCBdata, SqList_f *partTable)
  103. {
  104. int pos, arr[ 20] = { 0};
  105. LNode *p;
  106. p = PCBdata->Next;
  107. while (p)
  108. {
  109. if(p->data.pPagetable->elem[ 0].DistbutSt == Unallocated)
  110. {
  111. if(SelectPart(&(p->data), partTable, arr))
  112. {
  113. MallocMemory(&(p->data), partTable, arr);
  114. }
  115. }
  116. p = p->Next;
  117. }
  118. }
  119. void PrintProQueue(LinkList L)
  120. {
  121. int i = 0;
  122. L = L->Next;
  123. while(L)
  124. {
  125. printf( " -----------------------------\n");
  126. printf( "|进程名 | 申请大小 |\n");
  127. printf( "| %s | %4d |\n", L->data.Name, L->data.MemorySize);
  128. printf( "%s页表信息如下:\n| 页号 | 块号 | 是否分配 |\n", L->data.Name);
  129. for (i = 0; i < L->data.pPagetable->length; i++)
  130. printf( "| %4d | %4d | %4s |\n", i , L->data.pPagetable->elem[i].BlockNum,
  131. L->data.pPagetable->elem[i].DistbutSt == Allocated? "是" : "否");
  132. L = L->Next;
  133. }
  134. printf( " ----------------------------------------\n");
  135. }
  136. void PrintPartTable(PartTable L)
  137. {
  138. int i = 0, j = 0;
  139. printf( " ----------------------------------------\n");
  140. printf( "|分区号 | 起始位置 | 分区大小 | 是否分配 |\n");
  141. for (i = 0; i < L.length; ++i)
  142. printf( "| %2d | %4d | %4d | %4s |\n",
  143. i , L.elem[i].PartStartAddr, PageSize , strcmp(L.elem[i].Name, "") ? L.elem[i].Name : "否");
  144. printf( " ----------------------------------------\n");
  145. }

main


  
  1. #include "MemoryManage.h"
  2. /* 实验08 基本分页 */
  3. void InputPCBData(PCBList * pPCBdata)
  4. {
  5. PCBType e = {{ 0}, 0, NULL};
  6. strcpy(e.Name, "P1");
  7. e.MemorySize = 16;
  8. InitList_y(&(e.pPagetable));
  9. LoadPages(e.pPagetable, e.MemorySize);
  10. InsertProcess(*pPCBdata,e);
  11. strcpy(e.Name, "P2");
  12. e.MemorySize = 32;
  13. InitList_y(&(e.pPagetable));
  14. LoadPages(e.pPagetable, e.MemorySize);
  15. InsertProcess(*pPCBdata,e);
  16. strcpy(e.Name, "P3");
  17. e.MemorySize = 48;
  18. InitList_y(&(e.pPagetable));
  19. LoadPages(e.pPagetable, e.MemorySize);
  20. InsertProcess(*pPCBdata,e);
  21. strcpy(e.Name, "P4");
  22. e.MemorySize = 96;
  23. InitList_y(&(e.pPagetable));
  24. LoadPages(e.pPagetable, e.MemorySize);
  25. InsertProcess(*pPCBdata,e);
  26. strcpy(e.Name, "P5");
  27. e.MemorySize = 100;
  28. InitList_y(&(e.pPagetable));
  29. LoadPages(e.pPagetable, e.MemorySize);
  30. InsertProcess(*pPCBdata,e);
  31. }
  32. void SettingPage(PartTable * pPartdata)
  33. {
  34. PartiType se = { 0, { 0}};
  35. int Num = ( 512 - 16) / PageSize , i;
  36. for (i = 0; i < Num; ++i)
  37. {
  38. se.PartStartAddr = 16 + i * PageSize;
  39. InsertTable_f(pPartdata, i + 1, se);
  40. }
  41. }
  42. //0 - 15Kb 操作系统占用 总大小512KB
  43. int main(void)
  44. {
  45. PCBList PCBdata; //PCBdata里面存放原始PCB数据
  46. PartTable partTable; //分区表
  47. char PcbName[NAME_MAXSIZE] = { 0}, choice;
  48. PCBType PCBe = {{ 0}, 0, NULL};
  49. PartiType Parte = { 0, 0};
  50. PCBType *pcb = NULL;
  51. LNode *p;
  52. int i, size, pos, arr[ 20] = { 0}, k = 0;
  53. InitList_f(&partTable);
  54. SettingPage(&partTable);
  55. InitLinkList(&PCBdata);
  56. InputPCBData(&PCBdata);
  57. InitAllocation(PCBdata, &partTable);
  58. PrintProQueue(PCBdata);
  59. PrintPartTable(partTable);
  60. while( true)
  61. {
  62. system( "cls");
  63. PrintProQueue(PCBdata);
  64. PrintPartTable(partTable);
  65. printf( " ================================================\n");
  66. printf( "| 1.结 束 进 程 |\n");
  67. printf( "| 2.添 加 进 程 |\n");
  68. printf( "| 3.退 出 系 统 |\n");
  69. printf( " ================================================\n");
  70. printf( "请选择:");
  71. fflush( stdin);
  72. scanf( "%c",&choice);
  73. switch (choice)
  74. {
  75. case '1':
  76. printf( "要结束的进程名:");
  77. scanf( "%s",PcbName);
  78. for (p = PCBdata->Next, i = 1; p && strcmp(PcbName, p->data.Name); i++, p = p->Next);
  79. if(!p)
  80. {
  81. printf( "进程名输入错误!\n");
  82. break;
  83. }
  84. DeleteProsess(PCBdata, i, &PCBe);
  85. k = 0;
  86. for(i = 0; i < partTable.length; i++)
  87. {
  88. if(! strcmp(PcbName, partTable.elem[i].Name))
  89. {
  90. arr[k++] = i;
  91. }
  92. }
  93. FreeMemory(arr, k, &partTable);
  94. SearchSpace(PCBdata, &partTable);
  95. break;
  96. case '2':
  97. printf( "请输入添加的进程名,进程所占内存大小:");
  98. scanf( "%s%d",PcbName , &size);
  99. strcpy(PCBe.Name, PcbName);
  100. PCBe.MemorySize = size;
  101. InitList_y(&(PCBe.pPagetable));
  102. LoadPages(PCBe.pPagetable, PCBe.MemorySize);
  103. if(SelectPart(&(PCBe), &partTable, arr))
  104. MallocMemory(&(PCBe), &partTable, arr);
  105. InsertProcess(PCBdata, PCBe);
  106. break;
  107. case '3':
  108. return 0;
  109. default:
  110. printf( "选择项输入错误,重新选择!\n");
  111. break;
  112. }
  113. PrintProQueue(PCBdata);
  114. PrintPartTable(partTable);
  115. system( "pause");
  116. }
  117. return 0;
  118. }

 

五、模拟动态分区分配

介绍

list.h


  
  1. #ifndef _List_h_
  2. #define _List_h_
  3. #include "Data.h"
  4. //******* 链表 *******//
  5. Status InitLinkList(LinkList *L);
  6. void PCBAssign(PCBType *e1, PCBType e2);
  7. Status GetElemt_L(LinkList L,int i,PCBType *e);
  8. Status ListInsert_L(LinkList L,PCBType e);
  9. Status ListDelete_L(LinkList L,int i,PCBType *e);
  10. //****** 动态顺序表 ******//
  11. void PartiAssign(PartiType *e1, PartiType e2);
  12. Status InitList_Sq(SqList *L);
  13. Status ListInsert_Sq(SqList *L,int i,PartiType e);
  14. Status ListDelete_Sq(SqList *L,int i,PartiType *e);
  15. #endif

MemoryManage.h


  
  1. #ifndef _MemoryManage_h_
  2. #define _MemoryManage_h_
  3. #include "List.h"
  4. //***** PCB链表操作 *****//
  5. Status InsertProcess(LinkList Q,PCBType e);
  6. Status DeleteProsess(LinkList Q,int i,PCBType *e);
  7. //***** 分区表操作 *****//
  8. Status InsertTable(SqList *L, int i, PartiType e);
  9. Status DeleteTable(SqList *L, int i, PartiType *e);
  10. int SelectPart(PCB* pPCB, SqList *pPartTable, AllocatStrategy AS);
  11. int MallocMemory(PCB *pe, SqList *pPartTable,int i);
  12. void SearchSpace(PCBList PCBdata, SqList *partTable, AllocatStrategy AS);
  13. void FreeMemory(int pos, SqList *pPartTable);
  14. void InitAllocation(PCBList PCBdata, PartTable *partTable, AllocatStrategy AS);
  15. void PrintProQueue(LinkList L);
  16. void PrintPartTable(PartTable L);
  17. #endif

实现

list.c


  
  1. #include "List.h"
  2. Status InitLinkList(LinkList *L)
  3. {
  4. *L = (LinkList) malloc( sizeof(LNode));
  5. strcpy((*L)->data.Name, "");
  6. (*L)->Next = NULL;
  7. return OK;
  8. }
  9. void PCBAssign(PCBType *e1, PCBType e2)
  10. {
  11. strcpy(e1->Name,e2.Name);
  12. e1->DistbutSt = e2.DistbutSt;
  13. e1->MemorySize = e2.MemorySize;
  14. e1->StartAddress = e2.StartAddress;
  15. }
  16. Status GetElemt_L(LinkList L,int i,PCBType *e)
  17. {
  18. LinkList p = L->Next; //指向第j个结点
  19. int j = 1; //从第一个开始往后找
  20. while ( p && j < i ) //p不为空且j < i
  21. {
  22. p = p->Next;
  23. ++j;
  24. } //p为空,说明链表循环结束,也没有到第i个结点 j==i
  25. if (!p || j > i) //因为此处对i 没有做判断 如果 i==0 或 负数 条件成立
  26. //对于 i == j == 1 的情况则不用循环正好 返回
  27. {
  28. return ERROR;
  29. }
  30. *e = p->data; //通过寻址改变了 该地址内存中元素的值
  31. return OK;
  32. }
  33. //链表中按照优先级:从大到小排序插入
  34. Status ListInsert_L(LinkList L,PCBType e) //这样修改应该不对 p = *L出错
  35. {
  36. LinkList p = L, s;
  37. while (p->Next)
  38. p = p->Next;
  39. s = (LinkList) malloc( sizeof(LNode));
  40. PCBAssign(&s->data, e);
  41. s->Next = p->Next;
  42. p->Next = s;
  43. return OK;
  44. }
  45. //链表中头部删除
  46. Status ListDelete_L(LinkList L,int i,PCBType *e)
  47. {
  48. LinkList p = L, q;
  49. int j = 0;
  50. while (p->Next && j < i -1)
  51. {
  52. p = p->Next; ++j;
  53. }
  54. if(!p->Next || j > i - 1)
  55. return ERROR;
  56. q = p->Next;
  57. p->Next = q->Next;
  58. PCBAssign(e, q->data);
  59. free(q);
  60. return OK;
  61. }
  62. // 初始化 ///
  63. void PartiAssign(PartiType *e1, PartiType e2)
  64. {
  65. e1->PartitionSize = e2.PartitionSize;
  66. e1->PartStartAddr = e2.PartStartAddr;
  67. strcpy(e1->Name, e2.Name);
  68. }
  69. Status InitList_Sq(SqList *L)
  70. {
  71. //构造一个空的线性表L
  72. L->elem = (PartiType *) malloc((LIST_INIT_SIZE)* sizeof(PartiType));
  73. if(!L->elem) return ERROR; //存储分配失败
  74. L->length = 0; //空表长度为0
  75. L->listsize = LIST_INIT_SIZE; //初始存储的容量
  76. return OK;
  77. }
  78. //在顺序线性表L中第i个位置之前插入新的元素e
  79. Status ListInsert_Sq(SqList *L,int i,PartiType e)
  80. {
  81. //在顺序线性表L中第i个位置之前插入新的元素e
  82. //i的合法值为1 <= i <= ListLength_Sq(L)+1
  83. PartiType *q, *p, *newbase;
  84. if(i < 1 || i > L->length + 1 ) return ERROR; //i值不合法
  85. if(L->length >= L->listsize){ //当前存储空间已满,增加分配
  86. newbase = (PartiType *) realloc(L->elem
  87. ,(L->listsize + LISTINCREMENT)* sizeof(PartiType));
  88. if(!newbase) return ERROR; //存储分配失败
  89. L->elem = newbase; //新基址
  90. L->listsize += LISTINCREMENT; //增加存储容量
  91. }
  92. q = &(L->elem[i - 1]); //q为插入位置
  93. for(p = &(L->elem[L->length -1]);p >= q; --p)
  94. PartiAssign((p+ 1),*p); //插入位置及之后的元素右移
  95. PartiAssign(q ,e); //插入e
  96. L->length++;
  97. return OK;
  98. }
  99. //在顺序线性表L中删除第i个元素,并用e返回其值
  100. Status ListDelete_Sq(SqList *L,int i,PartiType *e)
  101. {
  102. //在顺序线性表L中删除第i个元素,并用e返回其值
  103. //i的合法值为1 <= i <= ListLength_Sq(L)
  104. PartiType *p,*q;
  105. if((i < 1) || (i > L->length))
  106. return ERROR; //i值不合法
  107. p = &(L->elem[i -1]); //p为被删除元素的位置
  108. PartiAssign(e, *p); //将被删除元素的值赋给e (待定)
  109. q = L->elem + L->length -1; //移动到表尾元素的位置
  110. for (++p;p<=q;++p)
  111. PartiAssign((p -1), *p); //被删除元素之后的元素左移
  112. L->length--;
  113. return OK;
  114. }

 


  
  1. #include "MemoryManage.h"
  2. extern int CF_i;
  3. //***** PCB链表操作 *****//
  4. Status InsertProcess(LinkList Q,PCBType e)
  5. {
  6. return ListInsert_L(Q, e);
  7. }
  8. Status DeleteProsess(LinkList Q, int i,PCBType *e)
  9. {
  10. return ListDelete_L(Q ,i,e);
  11. }
  12. //***** 分区表操作 *****//
  13. Status InsertTable(SqList *L, int i, PartiType e)
  14. {
  15. return ListInsert_Sq(L,i, e);
  16. }
  17. Status DeleteTable(SqList *L, int i, PartiType *e)
  18. {
  19. return ListDelete_Sq(L, i, e);
  20. }
  21. //返回第几个内存块,从1开始,若返回0,则代表错误
  22. int SelectPart(PCB* pPCB, SqList *pPartTable,AllocatStrategy AS)
  23. {
  24. int i;
  25. int BestArr[ 20] = { 0}, k = 0, min = 500, min_i = -1;
  26. if( AS == FirstPriority)
  27. {
  28. for (i = 0; i < pPartTable->length; ++i)
  29. if(!strcmp(pPartTable->elem[i].Name, "") && pPartTable->elem[i].PartitionSize >= pPCB->MemorySize)
  30. return i + 1;
  31. } else if( AS == BestAdapt)
  32. {
  33. 以下补充 /
  34. for(i = 0; i < pPartTable->length; ++i){
  35. if(!strcmp(pPartTable->elem[i].Name, "") && pPartTable->elem[i].PartitionSize >= pPCB->MemorySize)
  36. if(pPartTable->elem[i].PartitionSize - pPCB->MemorySize < min){
  37. min = pPartTable->elem[i].PartitionSize - pPCB->MemorySize;
  38. min_i = i;
  39. }
  40. }
  41. return min_i+ 1;
  42. } else if( AS == CycleFirst)
  43. {
  44. int flag = 0;
  45. 以下补充 /
  46. for(i = CF_i; i < pPartTable->length; i = (i+ 1)%(pPartTable->length)){
  47. if(!strcmp(pPartTable->elem[i].Name, "") && pPartTable->elem[i].PartitionSize >= pPCB->MemorySize){
  48. CF_i = (i+ 1)%pPartTable->length;
  49. return i + 1;
  50. }
  51. if(flag && i == CF_i){
  52. break;
  53. }
  54. if(i == CF_i){
  55. flag = 1;
  56. }
  57. }
  58. return 0;
  59. } else
  60. {
  61. printf( "算法选择有误!\n");
  62. }
  63. return ERROR;
  64. }
  65. //通过SelectPart查找是否存在可以分配的分区,在main函数中进行调用本方法进行内存的分配
  66. int MallocMemory(PCB *pe, SqList *pPartTable, int i)
  67. {
  68. PartiType se = { 0, 0, { 0}};
  69. 以下补充 /
  70. //修改PCB
  71. pe->DistbutSt = Allocated;
  72. pe->StartAddress = pPartTable->elem[i].PartStartAddr;
  73. if(pPartTable->elem[i].PartitionSize == pe->MemorySize){
  74. strcpy(pPartTable->elem[i].Name, pe->Name);
  75. } else {
  76. //修改分区使用说明表
  77. strcpy(pPartTable->elem[i].Name, "");
  78. pPartTable->elem[i].PartitionSize -= pe->MemorySize;
  79. pPartTable->elem[i].PartStartAddr += pe->MemorySize;
  80. //新建一个表目, 并插入分区表使用说明表
  81. strcpy(se.Name, pe->Name);
  82. se.PartitionSize = pe->MemorySize;
  83. se.PartStartAddr = pe->StartAddress;
  84. InsertTable(pPartTable, i+ 1, se);
  85. }
  86. return OK;
  87. }
  88. void InitAllocation(PCBList PCBdata, PartTable *pPartTable,AllocatStrategy AS)
  89. {
  90. LNode *p;
  91. int pos;
  92. p = PCBdata->Next;
  93. while (p)
  94. {
  95. if(p->data.DistbutSt == Unallocated)
  96. {
  97. pos = SelectPart(&(p->data), pPartTable, AS); //从1开始
  98. if(pos)
  99. {
  100. MallocMemory( &(p->data), pPartTable, pos - 1);
  101. }
  102. }
  103. p = p->Next;
  104. }
  105. }
  106. //回收指定位置的内存空间
  107. void FreeMemory( int pos, SqList *pPartTable) //没考虑 pos为0情况,没考虑删除后修改起始地址情况
  108. {
  109. PartiType se = { 0, 0, { 0}};
  110. int flag = 0;
  111. 以下补充 /
  112. if(pos != pPartTable->length -1){
  113. //为后一块分配
  114. if(!strcmp(pPartTable->elem[pos+ 1].Name, "")){
  115. strcpy(pPartTable->elem[pos].Name, "");
  116. pPartTable->elem[pos].PartitionSize += pPartTable->elem[pos+ 1].PartitionSize;
  117. strcpy(se.Name, pPartTable->elem[pos+ 1].Name);
  118. se.PartitionSize = pPartTable->elem[pos+ 1].PartitionSize;
  119. se.PartStartAddr = pPartTable->elem[pos+ 1].PartStartAddr;
  120. DeleteTable(pPartTable, pos+ 1, &se);
  121. flag = 1;
  122. }
  123. }
  124. if(pos != 0){
  125. //为前一块分配
  126. if(!strcmp(pPartTable->elem[pos -1].Name, "")){
  127. strcpy(pPartTable->elem[pos -1].Name, "");
  128. pPartTable->elem[pos -1].PartitionSize += pPartTable->elem[pos].PartitionSize;
  129. strcpy(se.Name, pPartTable->elem[pos -1].Name);
  130. se.PartitionSize = pPartTable->elem[pos -1].PartitionSize;
  131. se.PartStartAddr = pPartTable->elem[pos -1].PartStartAddr;
  132. DeleteTable(pPartTable, pos -1, &se);
  133. flag = 1;
  134. }
  135. }
  136. if(!flag){
  137. strcpy(pPartTable->elem[pos].Name, "");
  138. }
  139. }
  140. void SearchSpace(PCBList PCBdata, SqList *partTable, AllocatStrategy AS)
  141. {
  142. int pos;
  143. LNode *p;
  144. p = PCBdata->Next;
  145. while (p)
  146. {
  147. if(p->data.DistbutSt == Unallocated)
  148. {
  149. pos = SelectPart(&(p->data), partTable, AS); //从1开始
  150. if(pos)
  151. {
  152. MallocMemory(&(p->data), partTable, pos - 1);
  153. }
  154. }
  155. p = p->Next;
  156. }
  157. }
  158. void PrintProQueue(LinkList L)
  159. {
  160. int i = 0;
  161. L = L->Next;
  162. printf( " ----------------------------------------\n");
  163. printf( "|进程名 | 起始位置 | 申请大小 | 是否分配 |\n");
  164. while(L)
  165. {
  166. printf( "| %s | %4d | %4d | %4s |\n",
  167. L->data.Name, L->data.StartAddress, L->data.MemorySize, L->data.DistbutSt == Allocated? "是" : "否");
  168. L = L->Next;
  169. }
  170. printf( " ----------------------------------------\n");
  171. }
  172. void PrintPartTable(PartTable L)
  173. {
  174. int i = 0, j = 0;
  175. printf( " ----------------------------------------\n");
  176. printf( "|分区号 | 起始位置 | 分区大小 | 是否分配 |\n");
  177. for (i = 0; i < L.length; ++i)
  178. printf( "| %2d | %4d | %4d | %4s |\n",
  179. i + 1 , L.elem[i].PartStartAddr, L.elem[i].PartitionSize , strcmp(L.elem[i].Name, "") ? L.elem[i].Name : "否");
  180. printf( " ----------------------------------------\n");
  181. }

main


  
  1. #include "MemoryManage.h"
  2. /*实验06 动态分区分配
  3. */
  4. int CF_i;
  5. void InputPCBData(PCBList * pPCBdata)
  6. {
  7. PCBType e = {{ 0}, 0, 0, Unallocated};
  8. strcpy(e.Name, "P1");
  9. e.MemorySize = 16;
  10. InsertProcess(*pPCBdata,e);
  11. strcpy(e.Name, "P2");
  12. e.MemorySize = 32;
  13. InsertProcess(*pPCBdata,e);
  14. strcpy(e.Name, "P3");
  15. e.MemorySize = 48;
  16. InsertProcess(*pPCBdata,e);
  17. strcpy(e.Name, "P4");
  18. e.MemorySize = 96;
  19. InsertProcess(*pPCBdata,e);
  20. strcpy(e.Name, "P5");
  21. e.MemorySize = 100;
  22. InsertProcess(*pPCBdata,e);
  23. }
  24. void SetFixedZone(PartTable * pPartdata)
  25. {
  26. PartiType se = { 0, 0, { 0}};
  27. se.PartStartAddr = 16;
  28. se.PartitionSize = 512 - 16;
  29. strcpy(se.Name, "");
  30. InsertTable(pPartdata, 1, se);
  31. }
  32. //0 - 15Kb 操作系统占用 总大小512KB
  33. int main(void)
  34. {
  35. PCBList PCBdata; //PCBdata里面存放原始PCB数据
  36. PartTable partTable; //分区表
  37. char PcbName[NAME_MAXSIZE] = { 0}, choice;
  38. PCBType PCBe = {{ 0}, 0, 0, Unallocated};
  39. PartiType Parte = { 0, 0};
  40. PCBType *pcb = NULL;
  41. LNode *p;
  42. AllocatStrategy AS = CycleFirst; //FirstPriority, BestAdapt, CycleFirst
  43. //AllocatStrategy AS = BestAdapt;
  44. int i, size, pos;
  45. //分区表
  46. InitList_Sq(&partTable);
  47. SetFixedZone(&partTable);
  48. //进程表
  49. InitLinkList(&PCBdata);
  50. InputPCBData(&PCBdata);
  51. //初始化
  52. InitAllocation(PCBdata, &partTable, AS);
  53. CF_i = 0;
  54. PrintProQueue(PCBdata);
  55. PrintPartTable(partTable);
  56. while( true)
  57. {
  58. system( "cls");
  59. PrintProQueue(PCBdata);
  60. PrintPartTable(partTable);
  61. printf( " ================================================\n");
  62. printf( "| 1.结 束 进 程 |\n");
  63. printf( "| 2.添 加 进 程 |\n");
  64. printf( "| 3.退 出 系 统 |\n");
  65. printf( " ================================================\n");
  66. printf( "请选择:");
  67. fflush( stdin);
  68. scanf( "%c",&choice);
  69. switch (choice)
  70. {
  71. case '1':
  72. printf( "要结束的进程名:");
  73. scanf( "%s",PcbName);
  74. for (p = PCBdata->Next, i = 1; p && strcmp(PcbName, p->data.Name); i++, p = p->Next);
  75. if(!p)
  76. {
  77. printf( "进程名输入错误!\n");
  78. break;
  79. }
  80. DeleteProsess(PCBdata, i, &PCBe);
  81. for(i = 0; i < partTable.length; i++)
  82. {
  83. if(! strcmp(PcbName, partTable.elem[i].Name))
  84. {
  85. FreeMemory(i ,&partTable);
  86. break;
  87. }
  88. }
  89. SearchSpace( PCBdata, &partTable, AS);
  90. break;
  91. case '2':
  92. printf( "请输入添加的进程名,进程所占内存大小:");
  93. scanf( "%s%d",PcbName , &size);
  94. PCBe.DistbutSt = Unallocated;
  95. PCBe.StartAddress = 0;
  96. strcpy(PCBe.Name, PcbName);
  97. PCBe.MemorySize = size;
  98. pos = SelectPart(&(PCBe), &partTable, AS); //从1开始
  99. if(pos)
  100. MallocMemory(&(PCBe), &partTable, pos - 1);
  101. InsertProcess(PCBdata, PCBe);
  102. break;
  103. case '3':
  104. return 0;
  105. default:
  106. printf( "选择项输入错误,重新选择!\n");
  107. break;
  108. }
  109. PrintProQueue(PCBdata);
  110. PrintPartTable(partTable);
  111. system( "pause");
  112. }
  113. return 0;
  114. }

 

 


转载:https://blog.csdn.net/hebtu666/article/details/115171870
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场