文件系统存储空间管理算法设计与实现
(1)目的要求
如何充分有效地利用磁盘空间、并减少管理磁盘空间而带来的时间、 空间开销,是操作系统资源管理的任务之一。本实验模拟UNIX操作系统空闲块成组链接法,使学生对磁盘空闲空间的跟踪、分配和回收方法有更深入的理解。
(2)方法原理
UNIX操作系统将磁盘空闲块进行分组,每组的第一个块记录前一组空闲块的信息,最后一组信息记录在内存超级块中。当申请内存块时,若内存超级块中记录的空闲块数大于1,则进行出栈操作,分配栈顶的块。若内存超级块中记录的空闲块数等于1,则将该空闲块中暂存的下一组空闲块信息拷贝到超级块中,再分配该空闲块。当释放内存块时,若超级块中空闲块数未满,则块号入栈,释放该块。若已满,则将超级块中信息拷贝入该空闲块,清空超级块,该空闲块号入栈。UNIX操作系统利用磁盘空闲块来暂存磁盘空闲块的信息,可以节省大量内存,同时,块号的入栈、出栈操作可以快速实现非连续空间的分配和回收。
(3)主要实验仪器及材料
PC机, windows2000以上操作系统,C\C++\Java语言编程。
(4)掌握要点
设计空白块链数据结构,设定空闲块以N个盘块为一组,已划分成M组;可以用二维数组A[M][N]或结构体链表实现块链。A[0]表示超级块,管理最后一组的空闲块。A[0][0]表示超级块中管理的空闲块数,A[0][i]表示超级块中管理的第i个空闲块(i>0)。设计文件磁盘块申请命令和文件磁盘块释放命令,并进行命令解析;设计文件信息块数据结构,用于保存文件的磁盘块构成;创建、新增、删除文件块时访问文件信息块和空白块链数据结构。
(5)实验内容
通过用户随机给定的文件创建、新增块、文件删除等命令,算法仿真实现空白块成组链接法完成磁盘空闲空间的分配和释放,并完成实验报告。
(6)实现代码
#include <iostream>
#include <string>
using namespace std;
int main() {
//二维数组实现空闲块链
const int Max = 20;//20组
const int M = 5;
const int N = 11;//每组最大10个空闲块,第0块存放本组空闲块数量,第1块指向前一组
int A[Max][N] = {0};
for (int i = 0; i < M;i++) {
int count_free = 0;
for (int j = 1; j < N; j++) {
A[i][j] = 100*(i+1) + j;
count_free++;//空闲块数
}
if (i != 0) {//不是第0组
A[i][1] = i - 1;//A[i][1]保存前一组的下标
}
else {//是第0组
A[i][1] = -1;
}
A[i][0] = count_free;//A[i][0]保存本组空闲块数
}
int last_i = 0;//指向最后一组,即指向超级块
int last_j = 0;
cout << "初始空闲块链:" << endl
<< "组别 " << "空闲块数 " << "上一组"
<<" 空闲块 空闲块\t...\t...\t...\t...\t...\t...\t..."
<< endl;
for (int i = 0; i < M; i++) {
cout << i << ": \t";
int flag = 1;
for (int j = 0; j < N; j++) {
cout << A[i][j] << "\t";
last_j=j;
}
last_i = i;
cout << endl;
}
string op="";
string fileName="";
int fileSize = 0;
while (true) {
cout<< "--\t--\t--\t---\t---\t---\t---\t---\t---\t---\t---\t---\n"
<<"输入操作(touch/rm filename filesize):\n";
cin >> op>>fileName>>fileSize;
if (op == "touch") {//touch创建文件,申请空闲块
int obtainedSize = 0;
for (int i = 0; fileSize>obtainedSize;i++) {
//判断有无空闲块
if (A[last_i][0]<1&&A[last_i][1]<=0) {//全部空闲块耗尽,不再分配
cout << "已无可用空闲空间!" << endl;
break;
}
if (A[last_i][0] > 1) {//本组空闲块数大于1,分配本组的空闲块
A[last_i][last_j] = 0;
A[last_i][0] -= 1;
last_j--;
}
//本组空闲块数不足,分配上一组的空闲块
else {
int tmp = A[last_i][1];
A[last_i][last_j] = 0;
last_i = tmp;//更新超级块,前一组成为新的超级块
last_j = N - 1;
}
obtainedSize += 1;
}
}
else if (op == "rm") {//rm删除文件,归还块
int returnSize = 0;//已归还块数
for (int i = 0;fileSize > returnSize; i++) {
//判断当前组是否已满
if ((N-1)>A[last_i][0]) {//未满,加入本组
A[last_i][++last_j] = 100 * (last_i + 1) + last_j;
A[last_i][0] += 1;
}
else {//已满,引入超级块
int tem=last_i;
last_i += 1;
A[last_i][0] = 1;//将超级块空闲块数置1
A[last_i][1] = tem;
last_j = 1;//指向A[last_i][1]
}
returnSize++;
}
}
else if (op == "exit") {
break;
}
else {
cout << "错误输入!" << endl;
continue;
}
cout << "当前空闲块链:" << endl
<< "组别 " << "空闲块数 " << "上一组"
<< " 空闲块 空闲块\t...\t...\t...\t...\t...\t...\t..."
<< endl;
for (int i = 0; i <=last_i;i++) {//循环到超级块所在组
cout << i << ": \t";
if (i < last_i )
for (int j = 0; j < N;j++) {//循环N(11)次
cout << A[i][j] << "\t";
}
else if(i==last_i)
for (int j = 0; j <=last_j;j++) {//循环到最后一个空闲块
cout << A[i][j] << "\t";
}
cout << endl;
}
while (getchar() != '\n');//清空缓冲区
}
return 0;
}
(7)运行结果
初始空闲块链:
组别 空闲块数 上一组 空闲块 空闲块 ... ... ... ... ... ... ...
0: 10 -1 102 103 104 105 106 107 108 109 110
1: 10 0 202 203 204 205 206 207 208 209 210
2: 10 1 302 303 304 305 306 307 308 309 310
3: 10 2 402 403 404 405 406 407 408 409 410
4: 10 3 502 503 504 505 506 507 508 509 510
-- -- -- --- --- --- --- --- --- --- --- ---
输入操作(touch/rm filename filesize):
touch file1 6 //申请6个空闲块
当前空闲块链:
组别 空闲块数 上一组 空闲块 空闲块 ... ... ... ... ... ... ...
0: 10 -1 102 103 104 105 106 107 108 109 110
1: 10 0 202 203 204 205 206 207 208 209 210
2: 10 1 302 303 304 305 306 307 308 309 310
3: 10 2 402 403 404 405 406 407 408 409 410
4: 4 3 502 503 504
-- -- -- --- --- --- --- --- --- --- --- ---
输入操作(touch/rm filename filesize):
touch file 5 //申请5个空闲块
当前空闲块链:
组别 空闲块数 上一组 空闲块 空闲块 ... ... ... ... ... ... ...
0: 10 -1 102 103 104 105 106 107 108 109 110
1: 10 0 202 203 204 205 206 207 208 209 210
2: 10 1 302 303 304 305 306 307 308 309 310
3: 9 2 402 403 404 405 406 407 408 409
-- -- -- --- --- --- --- --- --- --- --- ---
输入操作(touch/rm filename filesize):
rm file3 13 //归还13个空闲块
当前空闲块链:
组别 空闲块数 上一组 空闲块 空闲块 ... ... ... ... ... ... ...
0: 10 -1 102 103 104 105 106 107 108 109 110
1: 10 0 202 203 204 205 206 207 208 209 210
2: 10 1 302 303 304 305 306 307 308 309 310
3: 10 2 402 403 404 405 406 407 408 409 410
4: 10 3 502 503 504 505 506 507 508 509 510
5: 2 4 602
-- -- -- --- --- --- --- --- --- --- --- ---
输入操作(touch/rm filename filesize):