記事ディレクトリ
可変パーティション管理により動的なメモリの適用と解放を実現
可変パーティション管理は、継続的なストレージ管理の実装方法であり、ジョブのサイズに応じてパーティションを分割し、分割の時間、サイズ、位置が動的である、動的パーティショニング方法です。
トピック
可変パーティション管理を使用して、動的なメモリの適用と解放を実現し、最大パーティション数と記憶領域サイズを制限し、各操作後にパーティション情報を表示します。メモリを申請する場合、要件を満たす空き領域を選択してパーティションを割り当てます。要件が満たされない場合、またはパーティション数の制限を超えた場合は、割り当て失敗のメッセージが表示され、メモリが解放されると、対応するメモリが割り当てられます。エリアは再利用され、新しいフリーエリアにマージされます。
アイデア
基礎となるメモリ割り当てメカニズムを実装するのはまだ多少難しいですが、ここでは可変パーティション管理をシミュレートするメカニズムを実装するために C 言語のみを使用します。このメカニズムをシミュレートするには、主に以下を実装する必要があります。
- パーティションとパーティションテーブルのデータ構造の表現
- パーティションの検索と割り当てのアルゴリズム
- パーティションの解放およびパーティションの結合操作
1. データ定義
パーティション情報の保存にはリンク リスト構造が使用され、空きパーティションと割り当て済みパーティションの 2 つのリンク リスト (空き領域と占有領域) をそれぞれ保存できます。もちろん、操作をそれほど複雑にしたくない場合は、リンク リストを使用して直接実行することもできます。ノードを定義するときに追加の属性を追加するだけで、パーティションが空きかどうかを判断できます。
#define MaxParts 5//定义分区最大数
#define Memaxsize 1024//定义内存大小
typedef struct Part//分区信息
{
int startAddress;//开始地址
int length;//分区长度
bool freee;//是否空闲
struct Part *next;//下一个分区
}Part;
Part partFirst={
0,Memaxsize,true,NULL};//初始化分区链表首项
typedef struct Distribution//分配结果
{
bool give;//是否获得分区
Part *part;//分区信息
int errorType;//错误类型 1 分区数过多 2 无足够大的分区
}Distribution;
2. パーティションの検索と割り当て
ユーザーがメモリ要求を行うときは、リンク リストを検索して要件を満たすパーティションを見つけてユーザーに割り当てる必要があります。パーティション割り当てには次のような多くのアルゴリズムがあります。
- 初回 (初回) 適応割り当てアルゴリズム:
チェーンの先頭から順に検索し、要件を満たす最初のパーティションが見つかったときに割り当てを開始します。このアルゴリズムでは、空きパーティション チェーンがアドレスの昇順でリンクされる必要があります。 - 次回 (サイクルの最初) の適応割り当てアルゴリズム:
毎回、チェーンの先頭から検索するのではなく、前回見つかった空きパーティションの次のパーティションから開始します。 - 最適な適応割り当てアルゴリズム:
毎回チェーンの先頭から順番に検索し、要件を満たす最小のパーティションを割り当てます。通常、空きパーティションはサイズの昇順に配置されます。 - ワーストフィット割り当てアルゴリズム:
毎回チェーンの先頭から順に検索し、要件を満たす最大のパーティションを割り当てます。 - 高速適応割り当てアルゴリズムは、
頻繁に使用される長さの空き領域に対して個別のリンク リストを設定します。
ここでは、シンプルで効率的な最初の(最初の)適応割り当てアルゴリズムが使用されます。
for(Part *temp = &partFirst;temp != NULL;temp = temp->next)//遍历内存分区表
{
if (temp->freee && temp->length > length)//找到足够大的分区
{
if (countPart + 1 > MaxParts) //已经达到最大分区数目,拒绝分配
{
errorType = 1;
break;
}
else //可以分配
countPart++;
temp->freee = false;//将分区标记为已分配
int tempLength = temp->length;
temp->length = length;//分区长度为申请长度
Part * tempNext = temp->next;//新建一个分区节点插入到当前分区节点之后
tempNext = (Part *)malloc(sizeof(Part));
tempNext->startAddress=temp->startAddress + temp->length;
tempNext->length=tempLength - length;
tempNext->freee=true;
tempNext->next=temp->next;
temp->next=tempNext;//这些步骤主要是为分割之后剩余的部分新建一个分区插入到分区链中,其中步骤不再赘述注释
disPart = temp;
dised = true;
break;
}
else if (temp->freee && temp->length == length)//大小相等直接修改空闲值
{
temp->freee = false;//这种情况不需要分割分区,直接分配
disPart = temp;
dised = true;
break;
}
if(temp->next==NULL)//没有找到满足大小的分区,返回错误信息
errorType = 2;
}
3. パーティションの解放とパーティションの結合
パーティションの解放では主に次の 4 つの状況が考慮されます。
- 左右がアイドル状態ではない
| プロセス A | プロセス X | プロセス B | - 右パーティション空き
| プロセス A | プロセス X | 空き | - 左側のパーティション フリー
| フリー | プロセス X | プロセス B | - 両側のパーティションは空き
|idle|process X|idle|
コードは次のとおりです。
for(Part *temp = &partFirst;temp != NULL;temp = temp->next)//遍历找释放分区的前一个分区
{
if (i+1 == n && temp->next != NULL)
{
if (temp->next->next != NULL && temp->next->next->freee == true) //后一个为空闲
{
if (temp->freee) //前后都为空闲,合并三个分区
{
Part *center = temp->next;
Part *right = temp->next->next;
Part *tempNext = temp->next->next->next;
temp->length += temp->next->length + temp->next->next->length;
temp->next = tempNext;
free(center);
center=NULL;
free(right);
right=NULL;
}
else //后面一个为空闲,合并两个分区
{
Part *right = temp->next->next;
Part *tempNext = temp->next->next->next;
temp->next->length += temp->next->next->length;
temp->next->next = tempNext;
temp->next->freee = true;
free(right);
right=NULL;
}
}
else //后一个不为空闲
{
if (temp->freee) //前一个为空闲,合并两个分区
{
Part *center = temp->next;
Part *tempNext = temp->next->next;
temp->length += temp->next->length;
temp->next = tempNext;
free(center);
center=NULL;
}
else//前后都不为空,只释放分区
temp->next->freee = true;
}
freee = true;
break;
}
else if(n==1)//特例判断,释放第一项,仅观察其后一分区是否为空
{
if(temp->next->freee)//释放分区并合并
{
Part *right = temp->next;
Part *tempNext = temp->next->next;
temp->length += temp->next->length;
temp->next = tempNext;
temp->freee = true;
free(right);
right=NULL;
}
else//只释放分区
temp->freee = true;
freee = true;
break;
}
i++;
}
4. その他
以上で可変パーティション管理をシミュレートする仕組みの主要部分が完成しましたので、あとは対話的な操作プロセスを適切に整理するだけです。
参照コードは次のとおりです。
void Menu()
{
int selected;
int value;
Distribution ret;
bool quit = false;
while (!quit)
{
printf("可变分区存储管理\n");
printf("1、申请内存\n");
printf("2、释放内存\n");
printf("3、退 出\n");
scanf("%d",&selected);
switch (selected)
{
case 1: printf("请输入申请内存大小:\n");
scanf("%d",&value);
ret = requestMe(value);
if (ret.give)
{
printf("\n分配成功.\n");
}
else
{
printf("\n分配失败.\n");
switch(ret.errorType)
{
case 1:
printf("%s.\n", "分区数达到限制");
break;
case 2:
printf("%s.\n", "没有足够大的分区可以分配");
break;
case 0:default:break;
}
}
break;
case 2:
printf("请输入要释放的分区序号:\n");
scanf("%d",&value);
freeMe(value);
break;
case 3:
quit = true;
break;
default:
break;
}
if(!quit)
showMe();//这是一个简单的遍历链表的函数
}
}