操作系统实验(九):设计文件系统

本文介绍了如何用C语言实现一个单级单用户的文件系统,涉及文件分配表(FAT),文件控制块(FCB),开放文件表等数据结构,详细描述了初始化、文件操作(创建、删除、打开、关闭)以及目录内容显示的过程,并强调了边界条件的处理。
摘要由CSDN通过智能技术生成

目录

实验 设计文件系统

一  实验目的

二  实验内容 1

三  实验过程及结果 2

四  实验总结 9

一  实验目的

(1) 掌握文件系统的工作原理。

(2) 理解文件系统的主要数据结构。

(3) 加深理解文件系统的内部功能和实现方法。

二  实验内容

2.1任务一

编写程序,设计并实现一个单级单用户的文件系统。可以在内存中开辟一

片空间模拟磁盘作为文件系统。文件以块为基本单位,一个块大小为 1024

个字节,共 1024 块。文件系统支持的最大文件数为 1024。

(1) 要求包含以下数据结构:

① 文件分配表 FAT,实现文件的链接分配。表条目指示文件的下一块的

块号。

② 文件控制块 FCB,包含文件名、文件大小、文件首块的块号等属性。

FCB 存储在根目录中。

③ 整个系统的打开文件表。显示当前哪些文件已被打开以及被多少个

进程打开。

(2) 要求提供以下操作:

① 文件系统的初始化:包括对 FAT、根目录和打开文件表的初始化。

② 文件创建/删除命令:create/delete。创建文件时指定如文件名、文件

大小等信息,并为其分配存储空间;删除文件时从根目录找到相应项,

回收其存储空间和 FCB。

③ 文件打开/关闭命令:open/close。打开文件先检查文件是否已打开,

若已打开则计数加 1,否则从根目录中找到相应项,加入打开文件表

中;关闭文件操作类似。

④ 显示目录内容命令:

ls。文件列示时要列出文件名和文件大小等信息。⑤ 进行文件操作时需考虑边界情况:如创建和打开文件时,需要检索是

否存在同名文件;删除文件时,如果文件正在被打开,则不被允许。

(3) 自行编写测试样例,验证文件系统的可靠性。

三  实验过程及结果

3.1编写 C 程序,设计并实现一个单级单用户的文件系统

(1) 要求包含以下数据结构:

①文件分配表 FAT,实现文件的链接分配。表条目指示文件的下一块的

块号。

② 文件控制块 FCB,包含文件名、文件大小、文件首块的块号等属性。

FCB 存储在根目录中。

③ 整个系统的打开文件表。显示当前哪些文件已被打开以及被多少个

进程打开。

(2) 要求提供以下操作:

① 文件系统的初始化:包括对 FAT、根目录和打开文件表的初始化。

② 文件创建/删除命令:create/delete。创建文件时指定如文件名、文件

大小等信息,并为其分配存储空间;删除文件时从根目录找到相应项,

回收其存储空间和 FCB

文件创建

文件删除

③ 文件打开/关闭命令:open/close。打开文件先检查文件是否已打开,

若已打开则计数加 1,否则从根目录中找到相应项,加入打开文件表

中;关闭文件操作类似。

文件打开

文件关闭

④ 显示目录内容命令:

ls。文件列示时要列出文件名和文件大小等信息。⑤ 进行文件操作时需考虑边界情况:如创建和打开文件时,需要检索是

否存在同名文件;删除文件时,如果文件正在被打开,则不被允许。

  1. 功能测试

文件的创建与删除

打开文件与关闭

边界测试

①同名文件

②删除打开的文件

退出文件系统

附录展示完整代码.

四  实验总结

通过本次实验,成功设计并实现了一个单级单用户的文件系统,主要包括文件分配表(FAT)、文件控制块(FCB)和打开文件表等数据结构的定义。文件系统的初始化、文件的创建与删除、文件的打开与关闭、目录内容的显示等操作均得以实现。通过编写测试样例,能够测试该文件系统的可靠性,充分考虑并且处理了边界情况,如同名文件的处理、删除打开的文件等。通过这个过程深入地理解了文件系统的内部结构和实现方法,包括文件的链接分配、根目录的管理以及打开文件的处理。

本次实验加深了对文件系统的工作原理,还加深了对操作系统内部功能和实现方法的认识。利用C语言的数据结构和文件操作相关的知识,提高了编程和问题解决的能力。通过不断调试和优化,成功地完成了一个可靠的文件系统,并通过测试验证了其稳定性和正确性。

附录

附录

算法详细代码

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #define BLOCK_SIZE 1024
  5. #define MAX_BLOCKS 1024
  6. #define MAX_FILES 1024
  7. #define MAX_FILENAME_LEN 50
  8. // 文件分配表 FAT
  9. typedef struct {
  10.     int nextBlock;
  11. } FATEntry;
  12. // 文件控制块 FCB
  13. typedef struct {
  14.     char filename[MAX_FILENAME_LEN];
  15.     int size;
  16.     int firstBlock;
  17. } FCBEntry;
  18. // 打开文件表
  19. typedef struct {
  20.     char filename[MAX_FILENAME_LEN];
  21.     int openCount;
  22. } OpenFileEntry;
  23. // 文件系统
  24. typedef struct {
  25.     FATEntry fat[MAX_BLOCKS];
  26.     FCBEntry rootDir[MAX_FILES];
  27.     OpenFileEntry openFiles[MAX_FILES];
  28. } FileSystem;
  29. FileSystem fs;
  30. // 初始化文件系统
  31. void initFileSystem() {
  32.     for (int i = 0; i < MAX_BLOCKS; i++) {
  33.         fs.fat[i].nextBlock = -1;
  34.     }
  35.     for (int i = 0; i < MAX_FILES; i++) {
  36.         strcpy(fs.rootDir[i].filename, "");
  37.         fs.rootDir[i].size = 0;
  38.         fs.rootDir[i].firstBlock = -1;
  39.         strcpy(fs.openFiles[i].filename, "");
  40.         fs.openFiles[i].openCount = 0;
  41.     }
  42. }
  43. // 创建文件
  44. void createFile(char* filename, int size) {
  45.     // 检查是否存在同名文件
  46.     for (int i = 0; i < MAX_FILES; i++) {
  47.         if (strcmp(fs.rootDir[i].filename, filename) == 0) {
  48.             printf("已存在同名文件。\n");
  49.             return;
  50.         }
  51.     }
  52.     // 寻找空闲的文件控制块
  53.     int fcbIndex = -1;
  54.     for (int i = 0; i < MAX_FILES; i++) {
  55.         if (strlen(fs.rootDir[i].filename) == 0) {
  56.             fcbIndex = i;
  57.             break;
  58.         }
  59.     }
  60.     if (fcbIndex == -1) {
  61.         printf("文件系统已满,无法创建更多文件。\n");
  62.         return;
  63.     }
  64.     // 寻找空闲的块
  65.     int blockIndex = -1;
  66.     for (int i = 0; i < MAX_BLOCKS; i++) {
  67.         if (fs.fat[i].nextBlock == -1) {
  68.             blockIndex = i;
  69.             break;
  70.         }
  71.     }
  72.     if (blockIndex == -1) {
  73.         printf("文件系统已满,无法分配更多块。\n");
  74.         return;
  75.     }
  76.     // 设置文件控制块和文件分配表
  77.     strcpy(fs.rootDir[fcbIndex].filename, filename);
  78.     fs.rootDir[fcbIndex].size = size;
  79.     fs.rootDir[fcbIndex].firstBlock = blockIndex;
  80.     // 计算需要分配的块数
  81.     int numBlocks = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
  82.     // 分配文件的块
  83.     for (int i = 0; i < numBlocks; i++) {
  84.         int nextBlockIndex = -1;
  85.         for (int j = blockIndex + 1; j < MAX_BLOCKS; j++) {
  86.             if (fs.fat[j].nextBlock == -1) {
  87.                 nextBlockIndex = j;
  88.                 break;
  89.             }
  90.         }
  91.         if (nextBlockIndex == -1) {
  92.             printf("文件系统已满,无法分配更多块。\n");
  93.             return;
  94.         }
  95.         fs.fat[blockIndex].nextBlock = nextBlockIndex;
  96.         blockIndex = nextBlockIndex;
  97.     }
  98.     fs.fat[blockIndex].nextBlock = -1; // 文件结束标志
  99.     printf("文件创建成功。\n");
  100. }
  101. // 删除文件
  102. void deleteFile(char* filename) {
  103.     // 查找文件
  104.     int fcbIndex = -1;
  105.     for (int i = 0; i < MAX_FILES; i++) {
  106.         if (strcmp(fs.rootDir[i].filename, filename) == 0) {
  107.             fcbIndex = i;
  108.             break;
  109.         }
  110.     }
  111.     if (fcbIndex == -1) {
  112.         printf("未找到文件。\n");
  113.         return;
  114.     }
  115.     // 检查文件是否正在被打开
  116.     for (int i = 0; i < MAX_FILES; i++) {
  117.         if (strcmp(fs.openFiles[i].filename, filename) == 0) {
  118.             printf("文件正在被打开,无法删除。\n");
  119.             return;
  120.         }
  121.     }
  122.     // 回收文件占用的块
  123.     int currentBlock = fs.rootDir[fcbIndex].firstBlock;
  124.     int nextBlock;
  125.     while (currentBlock != -1) {
  126.         nextBlock = fs.fat[currentBlock].nextBlock;
  127.         fs.fat[currentBlock].nextBlock = -1;
  128.         currentBlock = nextBlock;
  129.     }
  130.     // 清空文件控制块
  131.     strcpy(fs.rootDir[fcbIndex].filename, "");
  132.     fs.rootDir[fcbIndex].size = 0;
  133.     fs.rootDir[fcbIndex].firstBlock = -1;
  134.     printf("文件删除成功。\n");
  135. }
  136. // 打开文件
  137. void openFile(char* filename) {
  138.     // 查找文件
  139.     int fcbIndex = -1;
  140.     for (int i = 0; i < MAX_FILES; i++) {
  141.         if (strcmp(fs.rootDir[i].filename, filename) == 0) {
  142.             fcbIndex = i;
  143.             break;
  144.         }
  145.     }
  146.     if (fcbIndex == -1) {
  147.         printf("未找到文件。\n");
  148.         return;
  149.     }
  150.     // 检查文件是否已经打开
  151.     for (int i = 0; i < MAX_FILES; i++) {
  152.         if (strcmp(fs.openFiles[i].filename, filename) == 0) {
  153.             fs.openFiles[i].openCount++;
  154.             printf("文件打开成功,打开次数:%d\n", fs.openFiles[i].openCount);
  155.             return;
  156.         }
  157.     }
  158.     // 寻找空闲的打开文件表项
  159.     int openFileIndex = -1;
  160.     for (int i = 0; i < MAX_FILES; i++) {
  161.         if (strlen(fs.openFiles[i].filename) == 0) {
  162.             openFileIndex = i;
  163.             break;
  164.         }
  165.     }
  166.     if (openFileIndex == -1) {
  167.         printf("打开的文件过多,无法再打开更多文件。\n");
  168.         return;
  169.     }
  170.     // 添加文件到打开文件表
  171.     strcpy(fs.openFiles[openFileIndex].filename, filename);
  172.     fs.openFiles[openFileIndex].openCount = 1;
  173.     printf("文件打开成功,打开次数:1\n");
  174. }
  175. // 关闭文件
  176. void closeFile(char* filename) {
  177.     // 查找文件在打开文件表中的位置
  178.     int openFileIndex = -1;
  179.     for (int i = 0; i < MAX_FILES; i++) {
  180.         if (strcmp(fs.openFiles[i].filename, filename) == 0) {
  181.             openFileIndex = i;
  182.             break;
  183.         }
  184.     }
  185.     if (openFileIndex == -1) {
  186.         printf("文件未打开。\n");
  187.         return;
  188.     }
  189.     // 减少文件的打开计数
  190.     fs.openFiles[openFileIndex].openCount--;
  191.     // 如果计数为 0,则从打开文件表中移除
  192.     if (fs.openFiles[openFileIndex].openCount == 0) {
  193.         strcpy(fs.openFiles[openFileIndex].filename, "");
  194.     }
  195.     printf("文件关闭成功。\n");
  196. }
  197. // 显示目录内容
  198. void listDirectory() {
  199.     printf("目录内容:\n");
  200.     for (int i = 0; i < MAX_FILES; i++) {
  201.         if (strlen(fs.rootDir[i].filename) > 0) {
  202.             printf("文件: %s, 大小: %d, 文件首块: %d\n",
  203.                    fs.rootDir[i].filename, fs.rootDir[i].size, fs.rootDir[i].firstBlock);
  204.         }
  205.     }
  206. }
  207. int main() {
  208.     char command[100];  // 为了容纳整个命令,可以根据实际情况调整大小
  209.     char filename[MAX_FILENAME_LEN];
  210.     int size;
  211.     initFileSystem();
  212.     while (1) {
  213.         printf("Laix7&filesystem >");
  214.         scanf(" %[^\n]", command);
  215.         // 使用 sscanf 解析命令
  216.         char action[10];
  217.         if (sscanf(command, "%s", action) == 1) {
  218.             if (strcmp(action, "create") == 0) {
  219.                 if (sscanf(command, "%*s %s %d", filename, &size) == 2) {
  220.                     createFile(filename, size);
  221.                 } else {
  222.                     printf("错误命令格式!请重新输入\n");
  223.                 }
  224.             } else if (strcmp(action, "delete") == 0) {
  225.                 if (sscanf(command, "%*s %s", filename) == 1) {
  226.                     deleteFile(filename);
  227.                 } else {
  228.                     printf("错误命令格式!请重新输入\n");
  229.                 }
  230.             } else if (strcmp(action, "open") == 0) {
  231.                 if (sscanf(command, "%*s %s", filename) == 1) {
  232.                     openFile(filename);
  233.                 } else {
  234.                     printf("错误命令格式!请重新输入\n");
  235.                 }
  236.             } else if (strcmp(action, "close") == 0) {
  237.                 if (sscanf(command, "%*s %s", filename) == 1) {
  238.                     closeFile(filename);
  239.                 } else {
  240.                     printf("错误命令格式!请重新输入\n");
  241.                 }
  242.             } else if (strcmp(action, "ls") == 0) {
  243.                 listDirectory();
  244.             } else if (strcmp(action, "exit") == 0) {
  245.                 printf("退出文件系统...\n");
  246.                 break;
  247.             } else {
  248.                 printf("错误命令格式!请重新输入\n");
  249.             }
  250.         } else {
  251.             printf("错误命令格式!请重新输入\n");
  252.         }
  253.     }
  254.     return 0;
  255. }

【实验目的】 1. 了解文件系统的原理; 2. 用高级语言编写和调试一个简单的文件系统,模拟文件管理的工作过程。从而对各种文件操作命令的实质内容和执行过程有比较深入的了解。 【实验准备】 1.文件的逻辑结构  顺序文件  索引文件  索引顺序文件  直接文件和哈希文件 2.外存分配方式  连续分配  链接分配  索引分配 【实验内容】 1. 实验要求 要求设计一个 n个用户的文件系统,每次用户可保存m个文件,用户在一次运行中只能打开一个文件,对文件必须设置保护措施,且至少有Create、delete、open、close、read、write等命令。 2. 实验题目  设计一个10个用户的文件系统,每次用户可保存10个文件,一次运行用户可以打开5个文件。  程序采用二级文件目录(即设置主目录[MFD])和用户文件目录(UED)。另外,为打开文件设置了运行文件目录(AFD)。  为了便于实现,对文件的读写作了简化,在执行读写命令时,只需改读写指针,并不进行实际的读写操作。 因系统小,文件目录的检索使用了简单的线性搜索。文件保护简单使用了三位保护码:允许读写执行、对应位为 1,对应位为0,则表示不允许读写、执行。程序中使用的主要设计结构如下:主文件目录和用户文件目录( MFD、UFD)打开文件目录( AFD)(即运行文件目录)。 M D F 用户名 文件目录指针 用户名 文件目录指针 U F D 文件名 保护码 文件长度 文件名 A F D 打开文件名 打开保护码 读写指针
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

琉鹿者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值