#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>

// 文件地址缓冲区
int physic[300];

// 文件类型,1 表示普通文件
int style = 1;

// 当前目录
char cur_dir[10] = "c";

// 命令结构体
struct command {
    char com[10];
} cmd[12];

// 磁盘块结构体
struct block {
    int n;      // 空闲的盘快的个数
    int free[50];    // 存放空闲盘快的地址
    int a;      // 模拟盘快是否被占用
} 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; // 文件地址
        }
        i_node[i].file_length = -1;  // 文件长度
        i_node[i].file_style = -1;  // 文件类型
    }

    // 初始化根目录区信息
    for (i = 0; i < 64; i++) {
        strcpy(c[i].file_name, "");
        c[i].i_num = -1;
        strcpy(c[i].dir_name, "");
    }

    // 初始化存储空间
    for (i = 0; i < 200; i++) {
        memory[i].n = 0;      // 必须有这个
        memory[i].a = 0;
        for (j = 0; j < 50; j++) {
            memory[i].free[j] = -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++;  // 下一组空闲个数   注意在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");

    // 写入 memory 数组
    for (i = 0; i < 200; i++) {
        fwrite(&memory[i], sizeof(struct block), 1, fp);
    }

    // 写入超级块
    fwrite(&super_block, sizeof(struct block_super), 1, fp);

    // 写入 i 节点信息
    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");

    // 读取 memory 数组
    for (i = 0; i < 200; i++) {
        fread(&memory[i], sizeof(struct block), 1, fp);
    }

    // 读取超级块
    fread(&super_block, sizeof(struct block_super), 1, fp);

    // 读取 i 节点信息
    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; // 回收到栈中的哪个位置

        // 当超级块的空闲块个数为 50 时,栈满了
        if (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; // 标记为未被占用

        // 如果 m 为 -1,表示栈满了,将下一个文件地址中的盘块号回收到栈底
        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;
        }

        // 当超级块的空闲块个数为 1 时,分配最后一个盘块
        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; // 要跳过这次循环,下面的语句在 IF 中已经执行过
        }

        // 将栈中的相应盘块的地址写进 文件地址缓冲区
        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);

            // 将分配的磁盘地址写入 i 节点信息
            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() {
    FILE *fp;
    format(); // 初始化系统
    read_file(fp); // 从系统文件读取信息

    // 您的代码逻辑
    
    write_file(fp); // 将信息写入系统文件
    return 0;
}
C 语言实现简易 UNIX 文件系统模拟器 - 详细代码注释

原文地址: https://www.cveoy.top/t/topic/f1Dv 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录