C语言模拟UNIX文件系统:详细代码注释与实现
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
// 文件地址缓冲区
int physic[300];
// 文件类型 (1:普通文件, 0:目录)
int style = 1;
// 当前目录
char cur_dir[10] = "c";
// 命令结构体
struct command
{
char com[10];
} cmd[12];
// 磁盘块结构体
struct block
{
int n; // 空闲的盘快的个数
int free[50]; // 存放空闲盘快的地址
int a; // 模拟盘快是否被占用 (0:空闲, 1:占用)
} memory[200];
// 超级块结构体
struct block_super
{
int n; // 空闲的盘快的个数
int free[50]; // 存放进入栈中的空闲块
int stack[50]; // 存放下一组空闲盘快的地址
} super_block;
// i节点结构体
struct node
{
int file_style; // i节点文件类型
int file_length; // i节点文件长度
int file_address[100]; // i节点文件物理地址
} i_node[64];
// 目录项结构体
struct dir
{
char file_name[10]; // 文件名
int i_num; // 文件的结点号
char dir_name[10]; // 文件所在的目录
} c[64];
// 格式化函数,初始化系统数据
void format()
{
int i, j, k;
// 初始化超级块
super_block.n = 50;
for (i = 0; i < 50; i++)
{
super_block.free[i] = i; // 存放进入栈中的空闲块
super_block.stack[i] = 50 + i; // 存放下一组的盘块
}
// 初始化i节点信息
for (i = 0; i < 64; i++)
{
for (j = 0; j < 100; j++)
{
i_node[i].file_address[j] = -1; // 初始化文件地址为-1
}
i_node[i].file_length = -1; // 初始化文件长度为-1
i_node[i].file_style = -1; // 初始化文件类型为-1
}
// 初始化根目录区信息
for (i = 0; i < 64; i++)
{
strcpy(c[i].file_name, ""); // 初始化文件名为空字符串
c[i].i_num = -1; // 初始化i结点号为-1
strcpy(c[i].dir_name, ""); // 初始化目录名为为空字符串
}
// 初始化存储空间
for (i = 0; i < 200; i++)
{
memory[i].n = 0; // 初始化空闲块数量为0
memory[i].a = 0; // 初始化盘快状态为未占用
for (j = 0; j < 50; j++)
{
memory[i].free[j] = -1; // 初始化空闲块地址为-1
}
}
// 将空闲块的信息用成组链接的方法写进每组的最后一个块中
for (i = 0; i < 200; i++)
{
if ((i + 1) % 50 == 0)
{
k = i + 1;
for (j = 0; j < 50; j++)
{
if (k < 200)
{
memory[i].free[j] = k; // 下一组空闲地址
memory[i].n++; // 下一组空闲个数
k++;
}
else
{
memory[i].free[j] = -1;
}
}
memory[i].a = 0; // 标记为没有使用
continue; // 处理完用于存储下一组盘块信息的特殊盘块后,跳过本次循环
}
for (j = 0; j < 50; j++)
{
memory[i].free[j] = -1;
}
memory[i].n = 0;
}
printf("已经初始化完毕\n");
printf("欢迎进入UNIX文件模拟系统!!!\n\n");
}
// 将信息读入系统文件
void write_file(FILE *fp)
{
int i;
fp = fopen("system", "wb");
if (fp == NULL)
{
printf("打开文件system失败\n");
return;
}
for (i = 0; i < 200; i++)
{
fwrite(&memory[i], sizeof(struct block), 1, fp);
}
fwrite(&super_block, sizeof(struct block_super), 1, fp);
for (i = 0; i < 64; i++)
{
fwrite(&i_node[i], sizeof(struct node), 1, fp);
}
for (i = 0; i < 64; i++)
{
fwrite(&c[i], sizeof(struct dir), 1, fp);
}
fclose(fp);
}
// 读出系统文件的信息
void read_file(FILE *fp)
{
int i;
fp = fopen("system", "rb");
if (fp == NULL)
{
printf("打开文件system失败\n");
return;
}
for (i = 0; i < 200; i++)
{
fread(&memory[i], sizeof(struct block), 1, fp);
}
fread(&super_block, sizeof(struct block_super), 1, fp);
for (i = 0; i < 64; i++)
{
fread(&i_node[i], sizeof(struct node), 1, fp);
}
for (i = 0; i < 64; i++)
{
fread(&c[i], sizeof(struct dir), 1, fp);
}
fclose(fp);
}
// 回收磁盘空间
void callback(int length)
{
int i, j, k, m, q = 0;
for (i = length - 1; i >= 0; i--)
{
k = physic[i]; // 需要提供要回收的文件的地址
m = 49 - super_block.n; // 回收到栈中的哪个位置
if (super_block.n == 50) // 当super_block.n==50时 m=-1;的值
{ // super_block.n==50的时候栈满了,要将这个栈中的所有地址信息写进下一个地址中
for (j = 0; j < 50; j++)
{
memory[k].free[j] = super_block.free[j];
}
super_block.n = 0;
memory[k].n = 50;
}
memory[k].a = 0; // 标记盘快为未占用
if (m == -1)
{
m = 49; // 将下一个文件地址中的盘块号回收到栈底中
}
super_block.free[m] = physic[i]; // 将下一个文件地址中的盘块号回收到栈中
super_block.n++;
}
}
// 分配空间
void allot(int length)
{
int i, j, k, m, p;
for (i = 0; i < length; i++)
{
k = 50 - super_block.n; // 超级块中表示空闲块的指针
m = super_block.free[k]; // 栈中的相应盘块的地址
p = super_block.free[49]; // 栈中的最后一个盘块指向的地址
if (m == -1 || memory[p].a == 1) // 检测是否还有下一组盘块
{
printf("内存不足,不能够分配空间\n");
callback(length); // 回收空间
break;
}
if (super_block.n == 1)
{
memory[m].a = 1; // 将最后一个盘块分配掉
physic[i] = m; // 记录分配的盘块地址
super_block.n = 0; // 栈清空
for (j = 0; j < memory[m].n; j++) // 从最后一个盘块中取出下一组盘块号写入栈中
{
super_block.free[j] = memory[m].free[j];
super_block.n++;
}
continue; // 跳过本次循环
}
physic[i] = m; // 记录分配的盘块地址
memory[m].a = 1; // 标记盘快为占用
super_block.n--; // 栈中空闲块数量减少
}
}
// 创建文件
void create_file(char filename[], int length)
{
int i, j;
for (i = 0; i < 64; i++)
{
if (strcmp(filename, c[i].file_name) == 0)
{
printf("文件已经存在,不允许建立重名的文件\n");
return;
}
}
for (i = 0; i < 64; i++)
{
if (c[i].i_num == -1)
{
c[i].i_num = i; // 设置i结点号
strcpy(c[i].file_name, filename); // 设置文件名
strcpy(c[i].dir_name, cur_dir); // 设置文件所在目录
i_node[i].file_style = style; // 设置文件类型
i_node[i].file_length = length; // 设置文件长度
allot(length); // 分配空间
for (j = 0; j < length; j++)
{
i_node[i].file_address[j] = physic[j]; // 记录文件物理地址
}
break; // 找到空闲位置,结束循环
}
}
}
// 创建目录
void create_dir(char filename[])
{
style = 0; // 设置文件类型为目录
create_file(filename, 4); // 创建目录文件
style = 1; // 恢复文件类型为普通文件
}
int main()
{
format(); // 初始化系统
write_file(NULL); // 将系统信息写入文件system
read_file(NULL); // 从文件system读取系统信息
return 0;
}
原文地址: https://www.cveoy.top/t/topic/f1Du 著作权归作者所有。请勿转载和采集!