多用户多级目录文件系统的实现(代码+视频+报告+PPT)

122 阅读14分钟

   

课程名称 操作系统

题目名称 多用户多级目录文件系统的实现

学生学院 计算机学院

指导教师

  1. 年 1 月

目录

1需求分析2

1.1课题要求2

1.2设计要求2

1.3运行环境分析2

1.4开发工具简介2

2系统设计3

2.1整体设计思想3

2.2数据结构设计4

2.2.1文件系统结构体4

2.2.2主文件目录结构体4

2.2.3目录结构体5

2.2.4文件信息结构体5

2.2.5文件内容结构体5

2.2.6盘块结构体5

2.3系统功能设计6

2.4用户界面设计6

3系统实现7

3.1初始化功能7

3.2登录功能7

3.3注册功能8

3.4创建文件功能9

3.5删除文件功能9

3.6写入文件功能10

3.7打开文件功能11

3.8关闭文件功能11

3.9创建目录功能11

3.10改变目录功能12

3.11显示路径功能12

3.12列出文件目录功能12

3.13查看位示图功能13

3.14查看注册用户功能13

4运行情况14

4.1管理员登录情况14

4.2注册用户情况14

4.3创建文件、目录情况15

4.4写入文件情况15

4.5删除文件情况16

4.6切换目录情况16

4.7显示路径情况17

4.8切换目录情况17

4.9显示已注册用户情况18

4.10显示位示图情况18

5使用说明19

6体会建议20

7参考文献20

8源代码附件20

8.1main.c20

8.2command.c23

8.3file.c28

  1. 需求分析

    1. 课题要求
      本课程设计要求设计一个模拟的多用户多级目录的文件系统。通过具体的文件存储空间的管理、文件的物理结构、目录结构和文件操作的实现,加深对文件系统内部功能和实现过程的理解。

    2. 设计要求

  2. 在内存中开辟一个虚拟磁盘空间作为文件存储器,在其上实现一个多用户多目录的文件系统;

  3. 文件物理结构采用隐式链接方式;

  4. 磁盘空闲空间的管理选择位示图方式;

  5. 文件目录结构采用多用户多级目录结构,每个目录项包含文件名、物理地址、长度等信息,还可以通过目录项实现对文件的读和写的保护;

  6. 设计一个较实用的用户界面,方便用户使用,提供较丰富的文件操作。

  7. 运行环境分析
    本次采用macOS 10.12.系统(类Unix)进行开发,基于Xcode&Vim开发一个模拟的多用户多级目录的文件系统。

  8. 开发工具简介
    Xcode 是运行在操作系统Mac OS X上的集成开发工具(IDE),由苹果公司开发。Xcode是开发OS X 和 iOS 应用程序的最快捷的方式。Xcode 具有统一的用户界面设计,编码、测试、调试都在一个简单的窗口内完成。
    Vim是一个类似于Vi的著名的功能强大、高度可定制的文本编辑器,在Vi的基础上改进和增加了很多特性。VIM是自由软件。


  1. 系统设计
    1. 整体设计思想
      在内存中开辟1MB的空间来模拟多用户多级目录的文件系统。第一部分存放位示图,位示图元素类型为char,第二部分存放盘块信息。
      盘块区域分2040个盘块,每块512B,一共1020KB。 位示图元素个数为2040/8 = 255B = 0.25KB。

图 Chapter-1 空间分配图
系统初次运行时,首先进行系统初始化,包括申请内存空间、初始化位示图、初始化盘块文件、创建管理员账号。
首先进行登录判断,若密码正确则进入文件操作系统,若密码错误,则提示重新输入,直至密码正确。
当用户执行操作指令时,检查该操作指令是否是特殊指令,若是,则检查其用户权限,若是管理员,则执行,否则不执行。当是普通操作指令时,则不进行检查,直接执行。
普通指令操作包括文件的创建、删除、写入、打开、关闭;目录的创建、切换、显示;用户的登录、用户的退出。
特殊指令操作包括用户的注册、位示图的显示、已注册用户列表的查看。

图 Chapter-2 系统运行图

    1. 数据结构设计
      依据本课程设计要求,设计一个文件系统结构体、一个用于记录用户信息的主文件目录结构体、一个目录结构体、一个文件结构体以及一个盘块结构体。
      其中文件结构体分为文件信息结构体和文件内容结构体。
      文件系统结构体
      struct SYSTEM
      {
      char *start; //该文件系统起始地址
      long size; //该文件系统容量
      int disk_block_number; //文件系统中盘块的个数
      struct DISK *disk_head; //文件系统中盘块首地址
      };
      主文件目录结构体
      struct MFD //主文件目录,包含用户名、密码、指向用户目录的指针
      {
      char username[24]; //用户名
      char password[24]; //用户密码
      char right; //用户权限,1表示管理员,0表示一般用户
      struct MFD *next; //指向同级下一个用户的指针
      struct MULU *link; //指向该用户的文件目录指针
      };
      目录结构体
      struct MULU //目录结构体
      {
      char dirname[1024]; //目录名
      struct MULU *next; //指向同级的下一个目录的指针
      struct MULU *pre; //指向目录的父目录
      struct MULU *linkDir; //指向目录的子目录
      struct FIS *linkFile; //指向目录的文件
      };
      文件信息结构体
      struct FIS //文件信息结构体 File Information structe
      {
      char fileName[1024]; //文件名
      struct FIS *next; //指向同级的下一个文件的指针
      struct FCS *fileContex; //指向文件信息
      };
      文件内容结构体
      struct FCS //文件内容结构体 File Content structe
      {
      size_t size ; //文件大小
      char context[2048]; //文件内容
      char permissions[3];// 属性,读写执行,只计前3位
      int isOpen; //文件是否被打开
      struct DISK *disk; //指向所占的盘块链
      };
      盘块结构体
      struct DISK //盘块结构体
      {
      int diskNumber; //盘块号 盘块号从1开始 但是数组下标从0开始
      int diskSize; //盘块容量
      char *diskAddr; //盘块空间起始地址
      struct DISK *next; //指向下一个盘块
      };

    2. 系统功能设计

基于课程设计的要求,为该系统提供以下操作。其中register指令、showbp指令、who指令当且仅当以管理员身份登录才有权限执行。

  1. 使用方式 help
  2. 文件创建 create [File] [rwx]
  3. 打开文件 open [File]
  4. 关闭文件 close [File]
  5. 删除文件 delete [File]
  6. 文件的读 read [File]
  7. 文件的写 write [File]
  8. 创建目录 mkdir [DirName]
  9. 改变当前目录 cd [DirName]
  10. 显示当前路径 pwd
  11. 列出文件目录 dir [DirName]
  12. 清除屏幕 clear
  13. 登录用户 login [userName] [passWord]
  14. 注册用户 register [userName] [passWord]
  15. 查看位示图 showbp
  16. 查看已注册的用户 who
  17. 退出 logout
  18. 用户界面设计
    由于本系统是在Mac OS X下完成的,在一定程度上参考了Terminal的风格,所以用户设计界面方式为命令交互方式,命令操作方式大致与其相同。

图 Chapter-3 用户界面设计图


  1. 系统实现
    1. 初始化功能
      首先进行空间内存申请,为位示图和盘块信息分配对应的空间。其次是为该系统创建一个管理员账号,拥有不同于其他普通用户的权限。

图 Chapter-4 初始化功能

    1. 登录功能
      首先将指令分割,得到输入的账号密码,接着在系统中已注册的用户中进行遍历搜索,判断账号与密码是否一致。若一致,则返回成功,否则返回失败。

图 Chapter-5 用户登录功能

    1. 注册功能
      首先将指令分割,得到输入的账号密码,接着在系统中已注册的用户中进行遍历搜索,判断账号是否已存在,若存在,则注册失败,否则,注册成功,将该用户插入到已注册用户链表中,并为其创建一个用户目录。

图 Chapter-6 用户注册功能

    1. 创建文件功能
      首先获取需要创建的文件名,对当前目录下的文件进行遍历,若找到相同名字的文件名,则返回失败信息。
      否则检查位示图,查看是否有剩余盘块可供使用,若有剩余,则找到这个盘块地址,并设置文件相关信息,包括文件名,文件权限等。

图 Chapter-7 创建文件功能

    1. 删除文件功能
      删除文件时,首先检查是否有该文件,若存在该文件,则清空文件结构体,包括文件信息结构体以及文件内容结构体,并释放空间。
      接着进行回收盘块,并置位示图对应盘块号为空闲状态,编号为0。

图 Chapter-8 删除文件功能

    1. 写入文件功能
      首先,检查是否存在该文件,若存在,则打开该文件。判断写入的数据信息大小是否超过一个盘块,若超过则为其分配其他盘块,并置位示图中对应盘块编号为1。并记录文件大小信息以及文件数据信息。

图 Chapter-9 写入文件功能

    1. 打开文件功能
      文件结构体中有一个isOpen的变量,当该变量为1时,则表示文件被打开;当该变量为0时,则表示文件被关闭。
      当需要打开文件时,则检查是否存在该文件,若存在,则将变量isOpen置为1状态即可。
    2. 关闭文件功能
      文件结构体中有一个isOpen的变量,当该变量为1时,则表示文件被打开;当该变量为0时,则表示文件被关闭。
      当需要关闭文件时,则检查是否存在该文件,若存在,则将变量isOpen置为0状态即可。
    3. 创建目录功能
      首先检查当前子目录下是否存在相同名称的目录,若不存在,则创建一个新的子目录,并将该新的子目录插入到当前目录的子目录链表中。

图 Chapter-10 创建目录功能

    1. 改变目录功能
      改变目录分为多种方式,第一种是返回到上层目录,只需要将当前工作目录跳转到其父目录即可。
      第二种是返回用户根目录,此时只需要返回到用户工作目录即可。
      第三种是进入其子目录,这种情况下,要遍历其子目录,找到对应名称的目录,并将当前工作目录设置为该子目录。

图 Chapter-11 改变目录功能

    1. 显示路径功能
      在每次改变目录的时候,会自动记录当前工作目录,并将当前工作目录路径赋值给一个全局变量,当用户执行显示路径pwd指令时,输出该变量内容。
    2. 列出文件目录功能
      获取当前工作目录,并依次输出其子目录列表以及文件列表。对子目录列表和文件列表进行遍历查询,直到子目录指针或者文件指针为空为止。
    3. 查看位示图功能
      该功能仅限于管理员才可查看。首先根据位示图的元素个数进行遍历,在子循环中,检查每个元素的每一位Bit的状态,相应地输出。

图 Chapter-12 查看位示图功能

    1. 查看注册用户功能
      该功能仅限管理员可使用。该功能比较简单,只需要找到已注册文件列表,并遍历搜索并输出即可,直到遍历到最末端。

  1. 运行情况

    1. 管理员登录情况

    1. 注册用户情况


    1. 创建文件、目录情况

    1. 写入文件情况


    1. 删除文件情况

    1. 切换目录情况


    1. 显示路径情况

    1. 切换目录情况


    1. 显示已注册用户情况

    1. 显示位示图情况


  1. 使用说明
    首先,打开文件名为os的可执行程序,输入管理员账号密码,默认账号密码均为root。
    如果需要注册自己的普通账户,则在root账户下输入指令register 账号密码,若无提示,则说明注册成功。此时可输入logout退出root账号。
    使用指令dir可以查看当前工作目录下的子目录和文件,使用指令create可以创建文件,使用指令mkdir可以创建目录,使用delete可以删除文件。
    当需要读文件时,需先执行指令open 文件名,使文件为open状态,接着执行指令read,读完文件后,需要执行指令close关闭文件。
    其他指令具体操作方式可通过指令help进行实时查看,这里列出各种指令的详细使用方式。
    zhangxiaobai@/ roothelp使用方式help文件创建create[File][rwx]打开文件open[File]关闭文件close[File]删除文件delete[File]文件的读read[File]文件的写write[File]创建目录mkdir[DirName]改变当前目录cd[DirName]显示当前路径pwd列出文件目录dir[DirName]清除屏幕clear登录用户login[userName][passWord]注册用户register[userName][passWord]查看位示图showbp查看已注册的用户who退出logoutzhangxiaobai@/root help 使用方式 help 文件创建 create [File] [rwx] 打开文件 open [File] 关闭文件 close [File] 删除文件 delete [File] 文件的读 read [File] 文件的写 write [File] 创建目录 mkdir [DirName] 改变当前目录 cd [DirName] 显示当前路径 pwd 列出文件目录 dir [DirName] 清除屏幕 clear 登录用户 login [userName] [passWord] 注册用户 register [userName] [passWord] 查看位示图 showbp 查看已注册的用户 who 退出 logout zhangxiaobai@/ root

  1. 体会建议
    本次课程设计消耗比较长的时间,不过又学到了很多东西,使用对文件系统的原理的了解更加深刻了。同时,对C语言的应用也越来越得心应手了。
    本次课程设计中,从一开始我就参考了课本部分章节的内容,看了几遍后开始着手代码的编写,写到一半时,发现遇到个别问题,就一直卡在那里了。此时,又去网上参考了许多的文献资料,理清思路后,继续编写代码。
    其中有个目录组织方式使用索引节点的问题,我一开始的想法是认为目录组织方式就是文件盘块的组织方式,将文件占用的盘块放入索引节点中,但是写到一半发现好像审错题目要求了,就没继续写下去了,因为我原先使用的文件盘块组织方式是隐式链接的,要改过来的话需要较大的改动。
    本次课程设计从需求分析到代码实现以及文档编写大概花了6天左右,也从中学习到了很多,希望以后能够继续享受课程设计给我带来的快乐。

  2. 参考文献
    [1] 计算机操作系统(修订版), 汤子瀛等 ,西安电子科技大学出版社
    [2] 操作系统实验指导书,傅秀芬,广东工业大学(自编)
    [3] 计算机操作系统教程 ( 第二版 ), 张尧学、 史美林,清华大学出版社
    [4] 现代操作系统,A.S.Tanenbaum 著,陈向群等译机械工业出版社

  3. 源代码附件

    1. main.c

  4. //

  5. // main.c

  6. // os

  7. //

  8. // Created by 张小白 on 2018/1/3.

  9. // Copyright ? 2018年 张小白. All rights reserved.

  10. //

  11. #include <stdio.h>

  12. #include <stdlib.h>

  13. #include <time.h>

  14. #include "file.h"

  15. #include "command.h"

  16. char command[1024];

  17. char username[100];

  18. char password[100];

  19. int user_flag = 0;

  20. char absolute_path[1024];

  21. char relative_path[1024];

  22. char mesg[1024];

  23. extern char command_str[10][1024];

  24. extern int command_len;

  25. extern struct MFD *user;

  26. extern struct MULU *root;

  27. extern struct MFD *nowMainDir;

  28. void login_mesg(void)

  29. {

  30. time_t t;

  31. struct tm *lt;

  32. time (&t);

  33. lt = localtime(&t);

  34. printf("Last login: %d/%d/%d %d:%d:%d\n",lt->tm_year+1900, lt->tm_mon, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec);//输出结果

  35. sprintf(mesg,"zhangxiaobai@%s %s$ ",relative_path,username);

  36. printf("%s",mesg);

  37. }

  38. void create_mfd_user(char iusername[], char ipassword[]) //为用户分配MFD

  39. {

  40. user_create_mfd();

  41. }

  42. void login_register(void)

  43. {

  44. int flag = 0;

  45. while(1)

  46. {

  47. printf("login:");

  48. gets(command_str[1]);

  49. system("stty -echo");

  50. printf("password:");

  51. gets(command_str[2]);

  52. system("stty echo");

  53. printf("\n");

  54. if(checkAccount(command_str[1], command_str[2]) == 0)//登录成功

  55. {

  56. flag = 1;

  57. }

  58. if(flag == 1) //登录成功

  59. {

  60. strcpy(username,command_str[1]); //用户名

  61. strcpy(password,command_str[2]); //密码

  62. sprintf(absolute_path,"/"); //绝对路径

  63. sprintf(relative_path,"/"); //相对路径

  64. find_nowMainDir(username);

  65. printf("login successfully.\n");

  66. system("clear");

  67. break;

  68. }

  69. else //登录失败

  70. {

  71. printf("login failed, account or password error.\n");

  72. continue;

  73. }

  74. }

  75. }

  76. void creat_root(void)

  77. {

  78. strcpy(username,"root"); //注册的用户名

  79. strcpy(password,"root"); //注册的密码

  80. create_mfd_user(username,password);//为注册的用户分配MFD

  81. }

  82. int main(void)

  83. {

  84. int result;

  85. creat_root(); //创建管理员账号

  86. system_init(); //系统初始化

  87. while(1)

  88. {

  89. login_register(); //用户登录或注册

  90. login_mesg(); //登录信息

  91. while(1)

  92. {

  93. gets(command); //等待输入命令

  94. result = command_check(command); //解析命令

  95. if(result == 9) //退出登录

  96. {

  97. system("clear");

  98. break;

  99. }

  100. else if(result == -1) //无法解析命令

  101. printf("%s: command not found\r\n",command);

  102. else

  103. command_execute(result); //执行命令

  104. printf("%s",mesg);

  105. }

  106. }

  107. return (0);

  108. }

  109. command.c

  110. //

  111. // command.c

  112. // os

  113. //

  114. // Created by 张小白 on 2018/1/5.

  115. // Copyright ? 2018年 张小白. All rights reserved.

  116. //

  117. #include "command.h"

  118. #include "file.h"

  119. char command_str[10][1024];

  120. int command_len;

  121. extern char command[1024];

  122. extern char username[100];

  123. extern char password[100];

  124. extern char absolute_path[1024];

  125. extern char mesg[1024];

  126. extern struct MFD *nowMainDir;

  127. extern struct MULU *nowWorkDir;

  128. void help(void) //帮助信息

  129. {

  130. printf("使用方式 help\r\n");

  131. printf("文件创建 create [File] [rwx]\r\n");

  132. printf("打开文件 open [File]\r\n");

  133. printf("关闭文件 close [File]\r\n");

  134. printf("删除文件 delete [File]\r\n");

  135. printf("文件的读 read [File]\r\n");

  136. printf("文件的写 write [File]\r\n");

  137. printf("创建目录 mkdir [DirName]\r\n");

  138. printf("改变当前目录 cd [DirName]\r\n");

  139. printf("显示当前路径 pwd\r\n");

  140. printf("列出文件目录 dir [DirName]\r\n");

  141. printf("清除屏幕 clear\r\n");

  142. printf("登录用户 login [userName] [passWord]\r\n");

  143. if(nowMainDir->right == '1') //管理员账号申请注册

  144. {

  145. printf("注册用户 register [userName] [passWord]\r\n");

  146. printf("查看位示图 showbp\r\n");

  147. printf("查看已注册的用户 who\r\n");

  148. }

  149. printf("退出 logout\r\n");

  150. }

  151. void command_execute(int result)

  152. {

  153. if(result == 0)

  154. {

  155. create_file();

  156. }

  157. else if(result == 1)

  158. {

  159. open_file();

  160. }

  161. else if(result == 2)

  162. {

  163. read_file();

  164. }

  165. else if(result == 3)

  166. {

  167. write_file();

  168. }

  169. else if(result == 4)

  170. {

  171. close_file();

  172. }

  173. else if(result == 5)

  174. {

  175. delete_file();

  176. }

  177. else if(result == 6)

  178. {

  179. mk_dir();

  180. }

  181. else if(result == 7)

  182. {

  183. cd();

  184. }

  185. else if(result == 8)

  186. {

  187. dir();

  188. }

  189. else if(result == 9 || result == 14)

  190. {

  191. system("clear");

  192. }

  193. else if(result == 10)

  194. {

  195. ;

  196. }

  197. else if(result == 11)

  198. {

  199. if(nowMainDir->right == '1') //管理员账号申请注册

  200. {

  201. strcpy(username,command_str[1]); //注册的用户名

  202. strcpy(password,command_str[2]); //注册的密码

  203. create_mfd_user(command_str[1],command_str[2]);//为注册的用户分配MFD

  204. }

  205. else

  206. printf("you don't have the authority to register a user.\n");

  207. }

  208. else if(result == 12)

  209. {

  210. printf("%s\n",absolute_path);

  211. }

  212. else if(result == 13)

  213. {

  214. help();

  215. }

  216. else if(result == 15)

  217. {

  218. showBitMap();

  219. }

  220. else if(result == 16)

  221. {

  222. who();

  223. }

  224. }

  225. int command_check(char command[]) //命令分析

  226. {

  227. char *tmp;

  228. char command_tmp[1024];

  229. int i;

  230. int j;

  231. for(i=0;i<strlen(command);i++) //除去命令中多余的空格

  232. {

  233. if(command[i]== ' ' && command[i+1] == ' ')

  234. {

  235. for(j=i;j<(strlen(command)-1);j++)

  236. {

  237. command[j] = command[j+1];

  238. }

  239. command[j] = '\0';

  240. i--;

  241. }

  242. }

  243. command_len = 0;

  244. strcpy(command_tmp, command);

  245. tmp = strtok(command_tmp," ");//分割命令

  246. while(tmp) //将命令各部分放入数组中

  247. {

  248. strcpy(command_str[command_len],tmp);

  249. command_len++;

  250. tmp = strtok(NULL," ");

  251. }

  252. // printf("command:%s str[0]:%s\n",command,command_str[0]);

  253. if(strstr(command_str[0],"create") != NULL) //文件创建

  254. {

  255. return 0;

  256. }

  257. else if(strstr(command_str[0],"open") != NULL) //文件打开

  258. {

  259. return 1;

  260. }

  261. else if(strstr(command_str[0],"read") != NULL) //文件读

  262. {

  263. return 2;

  264. }

  265. else if(strstr(command_str[0],"write") != NULL) //文件写

  266. {

  267. return 3;

  268. }

  269. else if(strstr(command_str[0],"close") != NULL) //文件关闭

  270. {

  271. return 4;

  272. }

  273. else if(strstr(command_str[0],"delete") != NULL) //文件删除

  274. {

  275. return 5;

  276. }

  277. else if(strstr(command_str[0],"mkdir") != NULL) //建立目录

  278. {

  279. return 6;

  280. }

  281. else if(strstr(command_str[0],"cd") != NULL) //改变当前目录

  282. {

  283. return 7;

  284. }

  285. else if(strstr(command_str[0],"dir") != NULL) //列出文件目录

  286. {

  287. return 8;

  288. }

  289. else if(strstr(command_str[0],"logout") != NULL) //退出

  290. {

  291. return 9;

  292. }

  293. else if(strstr(command_str[0],"login") != NULL) //登录

  294. {

  295. return 10;

  296. }

  297. else if(strstr(command_str[0],"register") != NULL) //注册

  298. {

  299. return 11;

  300. }

  301. else if(strstr(command_str[0],"pwd") != NULL) //显示当前绝对路径

  302. {

  303. return 12;

  304. }

  305. else if(strstr(command_str[0],"help") != NULL) //帮助信息

  306. {

  307. return 13;

  308. }

  309. else if(strstr(command_str[0],"clear") != NULL) //清屏

  310. {

  311. return 14;

  312. }

  313. else if(strstr(command_str[0],"showbp") != NULL) //显示位示图

  314. {

  315. return 15;

  316. }

  317. else if(strstr(command_str[0],"who") != NULL) //查看系统用户

  318. {

  319. return 16;

  320. }

  321. else

  322. {

  323. return -1;

  324. }

  325. }

  326. file.c

  327. //

  328. // file.c

  329. // os

  330. //

  331. // Created by 张小白 on 2018/1/5.

  332. // Copyright ? 2018年 张小白. All rights reserved.

  333. //

  334. #include "file.h"

  335. #define getMemory(type) (type*)malloc(sizeof(type))

  336. #define SYSTEM_SIZE (1024 * 1024) //系统容量大小,单位为字节,总大小1024KB=1MB

  337. #define DiskMax 2040 //盘块个数

  338. #define DiskSize 512 //每个盘块的大小为512字节

  339. #define MAPMAX_M (2040 / 8) //位示图长度,即数组元素行数

  340. #define MAPMAX_N 8 //每行的位数

  341. int availableDisk = MAPMAX_M * MAPMAX_N; //可用文件块数

  342. char *maparr = NULL; //位示图指针

  343. extern char command[1024];

  344. extern char username[100];

  345. extern char password[100];

  346. extern int user_flag;

  347. extern char absolute_path[1024];

  348. extern char relative_path[1024];

  349. extern char mesg[1024];

  350. extern char command_str[10][1024];

  351. extern int command_len;

  352. struct SYSTEM *sysInfo = NULL;

  353. struct MFD *user = NULL;

  354. struct MFD *nowMainDir = NULL;

  355. struct MULU *nowWorkDir = NULL;

  356. int single_bit_read(unsigned char c,int pos) //读每一位 从右到左 依次为0~7位

  357. {

  358. unsigned char b_mask=0x01;

  359. b_mask = b_mask << pos;

  360. if((c&b_mask)==b_mask)

  361. return 1;

  362. else

  363. return 0;

  364. }

  365. void all_bit_read(unsigned char c,int direction) //依次输出它的每一个二进制位

  366. {

  367. int i;

  368. if(direction == 1)

  369. {

  370. for(i = MAPMAX_N-1; i>=0; i--)

  371. printf("%d ",single_bit_read(c, i));

  372. }

  373. else if(direction == 0)

  374. {

  375. for(i = 0; i<MAPMAX_N; i++)

  376. printf("%d ",single_bit_read(c, i));

  377. }

  378. }

  379. void single_bit_set(char* p_data, unsigned char position, int flag) //写每一位 从右到左 依次为1~8位

  380. {

  381. if(flag == 1)

  382. {

  383. *p_data |= (1<<(position-1));

  384. }

  385. else if(flag == 0)

  386. {

  387. *p_data &= ~(1<<(position-1));

  388. }

  389. }

  390. void system_init(void)

  391. {

  392. int i = 0;

  393. sysInfo = getMemory(struct SYSTEM);

  394. //为该文件系统申请1MB内存空间

  395. if ((sysInfo->start = (char *)malloc(SYSTEM_SIZE)) == NULL)

  396. {

  397. return ;

  398. }

  399. //该文件系统的盘块数

  400. sysInfo->disk_block_number = DiskMax;

  401. //该文件系统的容量大小

  402. sysInfo->size = SYSTEM_SIZE ;

  403. //第一部分为位示图的内存存储空间,将首地址赋值为位示图

  404. maparr = sysInfo->start;

  405. //初始化位示图,全部置0,表示该编号所对应的盘块为空闲状态

  406. for (i = 0; i < MAPMAX_M; i++)

  407. maparr[i] = 0;

  408. //剩余的内存空间用来存储盘块

  409. sysInfo->disk_head = create_disk_block_list( ((sysInfo->start) + MAPMAX_M),DiskSize,DiskMax);

  410. // for (i = 0; i < MAPMAX_M; i++)

  411. // {

  412. // single_bit_set(&maparr[i],7,0);

  413. // }

  414. // for (i = 0; i < MAPMAX_M; i++)

  415. // {

  416. // all_bit_read(maparr[i], 0);

  417. // printf("\n");

  418. // }

  419. // find_blank_file_disk(1);

  420. }

  421. //创建文件块链表,返回返回链表的头指针

  422. //datahead 第一块数据的地址,blockcap 一个文件块的大小,len 链表的长度

  423. struct DISK *create_disk_block_list(char *datahead, unsigned blockcap, unsigned len)

  424. {

  425. if (datahead == NULL || len == 0)

  426. {

  427. return NULL;

  428. }

  429. struct DISK *head;

  430. struct DISK *pnew;

  431. struct DISK *pold;

  432. head = pold = pnew = (struct DISK *)malloc(sizeof(struct DISK));

  433. for ( unsigned i = 0; i < len; i++)

  434. {

  435. pold->diskNumber = i+1; //盘块编号

  436. pold->diskSize = DiskSize; //盘块容量

  437. pold->diskAddr = datahead + i * blockcap; //盘块数据地址

  438. memset(pold->diskAddr, '\0', blockcap);

  439. if (i != len - 1)

  440. {

  441. pnew = (struct DISK *)malloc(sizeof(struct DISK));

  442. }

  443. else

  444. {

  445. pnew = NULL;

  446. }

  447. pold->next = pnew;

  448. pold = pnew;

  449. }

  450. return head;

  451. }

  452. //返回文件块的地址

  453. char * find_blank_file_disk(unsigned fileblockid)

  454. {

  455. struct DISK *fblock = sysInfo->disk_head;

  456. while (fblock->next != NULL)

  457. {

  458. if (fblock->diskNumber == fileblockid)

  459. {

  460. return fblock->diskAddr;

  461. }

  462. else

  463. {

  464. fblock = fblock->next;

  465. }

  466. }

  467. return NULL;

  468. }

  469. //在位示图中找到空闲的盘块

  470. int find_blank_block_id(void)

  471. {

  472. int i,j;

  473. for (i = 0; i < MAPMAX_M; i++)

  474. {

  475. for (j = 0; j < MAPMAX_N; j++)

  476. {

  477. if(single_bit_read(maparr[i], j) == 0) //第i行第j位 空闲

  478. return MAPMAX_N * i + j + 1;

  479. }

  480. }

  481. return 0;

  482. }

  483. void clear_stdin(void) //清除输入缓冲区

  484. {

  485. char ch;

  486. while((ch=getchar())!='\n'&&ch!=EOF);

  487. }

  488. void showMFD(void) //显示各个用户

  489. {

  490. struct MFD *q;

  491. if(user)

  492. q = user;

  493. else

  494. return ;

  495. while(q)

  496. {

  497. // printf("username:%s password:%s right:%c\n",q->username,q->password,q->right);

  498. q = q->next;

  499. }

  500. }

  501. int checkAccount(char iusername[],char ipassword[]) //检测用户是否正确

  502. {

  503. struct MFD *q;

  504. if(user)

  505. q = user;

  506. else

  507. return -1;

  508. while(q)

  509. {

  510. if(strcmp(q->username, iusername) == 0 && strcmp(q->password,ipassword) == 0)

  511. return 0;

  512. q = q->next;

  513. }

  514. return -1;

  515. }

  516. void who(void) //输出系统的所有已注册用户

  517. {

  518. struct MFD *q;

  519. if(user)

  520. q = user;

  521. else

  522. return ;

  523. // printf("\n");

  524. while(q)

  525. {

  526. printf("username:%s\tpassword:%s\tright:%c\t\n",q->username,q->password,q->right);

  527. q = q->next;

  528. }

  529. }

  530. //对各个用户的MFD进行链接

  531. void linkMFD(struct MFD *p) //对用户进行链接

  532. {

  533. struct MFD *a,*b;

  534. if(user==NULL)

  535. {

  536. p->next=user;

  537. user=p;

  538. }

  539. else

  540. {

  541. b=user;

  542. a=user->next;

  543. while(a) //找到最后一个结点

  544. {

  545. b=a;

  546. a=a->next;

  547. }

  548. b->next=p;

  549. p->next=a;

  550. }

  551. showMFD();

  552. }

  553. //为用户创建一个MFD

  554. void user_create_mfd(void)

  555. {

  556. struct MFD *p;

  557. struct MFD *q;

  558. q = user;

  559. while(q && strcmp(q->username,username) != 0)//判断当前登录的用户名或者注册的用户名是否已经存在

  560. {

  561. q=q->next;

  562. }

  563. if(q!=NULL) //该用户的MFD已经存在,则无需重新创建MFD

  564. {

  565. printf("register failed.the accounts exist already.\n");

  566. return ;

  567. }

  568. p=getMemory(struct MFD);

  569. strcpy(p->username,username);

  570. strcpy(p->password,password);

  571. if(strcmp(username, "root") == 0)

  572. p->right = '1'; //管理员

  573. else

  574. p->right = '0'; //普通用户

  575. p->next=NULL;

  576. p->link=getMemory(struct MULU);

  577. //初始化用户的根目录

  578. strcpy(p->link->dirname,username); //用户根目录名字

  579. p->link->next=NULL; //用户根目录是无同级目录的

  580. p->link->link=NULL; //子目录暂时为空

  581. p->link->pre=NULL; //用户根目录是无父目录的

  582. p->link->link1=NULL; //目录包含的文件暂时为空

  583. linkMFD(p); //将新建立的用户与已存在的用户进行链接

  584. }

  585. //对某一目录的文件进行链接

  586. void link_file(struct FIS *p)

  587. {

  588. struct MULU *b;

  589. struct FIS *a;

  590. b = nowWorkDir;

  591. if(b->link1==NULL)

  592. {

  593. b->link1=p;

  594. p->next=NULL;

  595. }

  596. else

  597. {

  598. a=b->link1;

  599. while(a->next)

  600. {

  601. a=a->next;

  602. }

  603. p->next=a->next;

  604. a->next=p;

  605. }

  606. }

  607. void create_file(void)

  608. {

  609. struct FIS *file;

  610. struct MULU *tmp;

  611. struct FIS *file1;

  612. int id = 0; //空闲盘块

  613. char *blank; //空闲盘块内存地址

  614. tmp = nowWorkDir;//当前工作目录

  615. file1 = tmp->link1;//指向当前目录所包含的文件

  616. while(file1 != NULL && strcmp(file1->fileName, command_str[1]) != 0)

  617. file1 = file1 -> next;

  618. if(file1 != NULL)

  619. {

  620. printf("create failed,this file name has been used.\n");

  621. return ;

  622. }

  623. id = find_blank_block_id(); //寻找第一个空闲盘块

  624. if(id == 0) //盘块号是从1开始的,所以当为0则说明找不到

  625. {

  626. printf("write failed,there is not enough disk to write\n");

  627. return ;

  628. }

  629. blank = find_blank_file_disk(id); //找到这个空闲盘块指向的内存空间地址

  630. // printf("id:%d\n",id);

  631. if(blank == NULL)

  632. {

  633. printf("can't find the memory address of this disk block.\n");

  634. return ;

  635. }

  636. file = getMemory(struct FIS); //文件结构体地址

  637. file->fileContex = getMemory(struct FCS);

  638. strcpy(file->fileName, command_str[1]);//文件名

  639. file->fileContex->size = 0;//文件大小默认为0

  640. // printf("str2:%s\n",command_str[2]);

  641. strcpy(file->fileContex->permissions, command_str[2]);//文件权限,注意,只能三位

  642. file->fileContex->isOpen = 0;//文件当前没有在运行

  643. file->fileContex->disk = NULL;//磁盘快初始化为空

  644. link_file(file);//将当前工作目录的文件进行链接

  645. }

  646. void find_nowMainDir(char *iusername)

  647. {

  648. nowMainDir = user;

  649. while(nowMainDir && strcmp(nowMainDir->username, iusername))//当前用户主目录

  650. {

  651. nowMainDir = nowMainDir->next;

  652. }

  653. nowWorkDir = nowMainDir->link;//当前工作目录

  654. // printf("用户名是%s 密码是%s 当前用户指向的根目录%s\n",nowMainDir->username,nowMainDir->password,nowWorkDir->dirname);

  655. }

  656. void dir(void)

  657. {

  658. int i=-1;

  659. struct MULU *m;

  660. struct FIS *r;

  661. m=nowWorkDir->link;//指向目录所包含的子目录

  662. r=nowWorkDir->link1;//指向目录所包含的文件

  663. printf("dir:");

  664. while(m) //对目录进行遍历

  665. {

  666. i = (i+1) % 5;

  667. if(i == 0)

  668. printf("\n%s\t",m->dirname);

  669. else

  670. printf("%s\t",m->dirname);

  671. m = m->next;

  672. }

  673. i = -1;

  674. printf("\n\nfile:");

  675. while(r)

  676. {

  677. i = (i+1) % 5;

  678. if(i == 0)

  679. printf("\n%s\t",r->fileName);

  680. else

  681. printf("%s\t",r->fileName);

  682. r = r->next;

  683. }

  684. printf("\n");

  685. }

  686. void open_file(void)

  687. {

  688. struct MULU *tmp;

  689. struct FIS *file;

  690. tmp = nowWorkDir;//当前工作目录

  691. file = tmp->link1;//指向当前目录所包含的文件

  692. while(file != NULL && strcmp(file->fileName, command_str[1]) != 0)

  693. file = file -> next;

  694. if(file == NULL)

  695. {

  696. printf("open failed,file does not exist.\n");

  697. return ;

  698. }

  699. file->fileContex->isOpen = 1;//打开文件

  700. }

  701. void close_file(void)

  702. {

  703. struct MULU *tmp;

  704. struct FIS *file;

  705. tmp = nowWorkDir;//当前工作目录

  706. file = tmp->link1;//指向当前目录所包含的文件

  707. while(file != NULL && strcmp(file->fileName, command_str[1]) != 0)

  708. file = file -> next;

  709. if(file == NULL)

  710. {

  711. printf("open failed,file does not exist.\n");

  712. return ;

  713. }

  714. file->fileContex->isOpen = 0;//关闭文件

  715. }

  716. void read_file(void)

  717. {

  718. struct MULU *tmp;

  719. struct FIS *file;

  720. tmp = nowWorkDir;//当前工作目录

  721. file = tmp->link1;//指向当前目录所包含的文件

  722. while(file != NULL && strcmp(file->fileName, command_str[1]) != 0)

  723. file = file -> next;

  724. if(file == NULL)

  725. {

  726. printf("read failed,file does not exist.\n");

  727. return ;

  728. }

  729. if(file->fileContex->isOpen == 1)

  730. printf("%s\n",file->fileContex->context); //输出内容

  731. else

  732. printf("please open the file first.\n");

  733. }

  734. void showBitMap(void)

  735. {

  736. int i = 0;

  737. printf("BitMap:\n");

  738. for (i = 0; i < MAPMAX_M; i++)

  739. {

  740. all_bit_read(maparr[i],0);

  741. printf("\n");

  742. }

  743. }

  744. void allocateDiskBlock(struct FIS *file,size_t len) //分配盘块

  745. {

  746. //盘块数组下标从0开始,盘块号从1开始算

  747. //盘块号 = MAPMAX_N * i + j + 1

  748. int i = 0, j = 0;

  749. size_t nowLen = 0;

  750. struct DISK *diskHead;

  751. struct DISK *disk;

  752. struct DISK *diskTmp;

  753. diskHead = getMemory(struct DISK);

  754. diskTmp = diskHead;

  755. file->fileContex->disk = diskHead;//分配一个不存放盘块数据的头指针

  756. for (i = 0; i < MAPMAX_M; i++)

  757. {

  758. for (j = 0 ; j < MAPMAX_N; j++)

  759. {

  760. if(single_bit_read(maparr[i],j) == 0)

  761. {

  762. if(nowLen < len)

  763. {

  764. nowLen++;

  765. disk = getMemory(struct DISK);

  766. diskTmp->next = disk;

  767. disk->next = NULL;

  768. disk->diskNumber = MAPMAX_N * i + j + 1;//盘块号计算公式

  769. disk->diskSize = DiskSize; //盘块大小

  770. single_bit_set(&maparr[i],j+1,1);

  771. diskTmp = disk;

  772. }

  773. else

  774. break;

  775. }

  776. }

  777. }

  778. // showBitMap();

  779. }

  780. void recycleDiskBlock(struct FIS *file) //回收盘块

  781. {

  782. struct DISK *tmp;

  783. struct DISK *tmp1;

  784. struct DISK *tmp2;

  785. int i,j;

  786. // i = 盘块号/MAPMAX_N

  787. // j = 盘块号%MAPMAX_N - 1

  788. tmp = file->fileContex->disk;//指向文件的第一个盘块,不包含盘块信息

  789. if(tmp == NULL)//该头盘块指针不存在,说明这个文件里面没内容,所以没占用盘块

  790. return ;

  791. tmp1 = tmp->next;

  792. free(tmp); //先清除时盘块头指针,因为不包含盘块数据

  793. while(tmp1)

  794. {

  795. tmp2 = tmp1;

  796. i = (int)(tmp1->diskNumber/MAPMAX_N);

  797. j = ((tmp1->diskNumber)%MAPMAX_N) - 1;

  798. single_bit_set(&maparr[i],j+1,0);

  799. tmp1 = tmp1->next;

  800. free(tmp2); //释放内存

  801. }

  802. }

  803. void write_file(void)

  804. {

  805. char content[2048];

  806. int i = 0;

  807. size_t old_size = 0;

  808. struct MULU *tmp;

  809. struct FIS *file;

  810. tmp = nowWorkDir;//当前工作目录

  811. file = tmp->link1;//指向当前目录所包含的文件

  812. while(file != NULL && strcmp(file->fileName, command_str[1]) != 0)

  813. file = file -> next;

  814. if(file == NULL) //文件不存在

  815. {

  816. printf("write failed,file does not exist.\n");

  817. return ;

  818. }

  819. if(file->fileContex->permissions[1] != '1') //检测是否有写的权限

  820. {

  821. printf("the file is not allowed to write.\n");

  822. return ;

  823. }

  824. printf("please input the content:(stop by #)");

  825. while( (content[i] = getchar()) != '#')

  826. i = (i + 1)%2048;

  827. content[i] = '\0';

  828. if(( availableDisk + (int)(file->fileContex->size) - (int)(strlen(content)) ) >= 0)

  829. {

  830. //可用盘块数目+文件已经占用的盘块数目-需要占用的盘块数目>= 0

  831. open_file(); //打开文件

  832. old_size = file->fileContex->size; //该文件原来的大小

  833. recycleDiskBlock(file);//重新写入该文件时,应当先回收掉原来占用的盘块,并释放空间

  834. strcpy(file->fileContex->context, content); //对文件内容赋值

  835. file->fileContex->size = strlen(content);// 对文件大小赋值

  836. // printf("file len:%lu\n",file->fileContex->size);

  837. availableDisk = availableDisk - (int)(file->fileContex->size) + (int)old_size; //剩余可用盘块数

  838. // printf("availe len:%d\n",availableDisk);

  839. allocateDiskBlock(file,file->fileContex->size);//分配盘块,这里假设长度多大,盘块就多少个

  840. clear_stdin(); //清除输入缓冲区

  841. close_file(); //关闭文件

  842. }

  843. else

  844. {

  845. printf("write failed,there is not enough disk to write\n");

  846. clear_stdin(); //清除输入缓冲区

  847. return ;

  848. }

  849. }

  850. void delete_file(void) //删除文件

  851. {

  852. struct MULU *tmp;

  853. struct FIS *file;

  854. struct FIS *tmp1;

  855. size_t old_size = 0;

  856. tmp = nowWorkDir;//当前工作目录

  857. file = tmp->link1;//指向当前目录所包含的文件

  858. while(file != NULL && strcmp(file->fileName, command_str[1]) != 0)

  859. file = file -> next;

  860. if(file == NULL)

  861. {

  862. printf("delete failed,file does not exist.\n");

  863. return ;

  864. }

  865. old_size = file->fileContex->size; //文件的大小

  866. recycleDiskBlock(file);//回收掉原来占用的盘块,并释放盘块指针空间

  867. availableDisk = availableDisk + (int)(file->fileContex->size); //可用盘块数

  868. if(strcmp(tmp->link1->fileName, file->fileName) == 0) //这个被删除的文件在第一个位置

  869. {

  870. if(tmp->link1->next) //第二个位置有文件

  871. nowWorkDir->link1 = tmp->link1->next;

  872. else //第二个位置没文件

  873. nowWorkDir->link1 = NULL;

  874. free(file);

  875. }

  876. else

  877. {

  878. tmp1 = tmp->link1;

  879. while(strcmp(tmp1->next->fileName, file->fileName) != 0) //这个被删除的文件在不第一个位置

  880. {

  881. tmp1 = tmp1->next;

  882. if(!(tmp1->next))

  883. break;

  884. }

  885. tmp1->next = file->next;

  886. free(file);

  887. }

  888. }

  889. void link_dir(struct MULU *dir)//对某一目录的同级子目录进行链接

  890. {

  891. struct MULU *b;

  892. struct MULU *a;

  893. b = nowWorkDir;

  894. if(b->link==NULL)

  895. {

  896. b->link=dir;

  897. dir->next=NULL;

  898. }

  899. else

  900. {

  901. a=b->link;

  902. while(a->next)

  903. {

  904. a=a->next;

  905. }

  906. dir->next=a->next;

  907. a->next=dir;

  908. }

  909. }

  910. void mk_dir(void) //创建目录

  911. {

  912. struct MULU *dir;

  913. struct MULU *tmp;

  914. struct MULU *dir1;

  915. tmp = nowWorkDir;//当前工作目录

  916. dir1 = tmp->link;//指向当前目录所包含的文件

  917. while(dir1 != NULL && strcmp(dir1->dirname, command_str[1]) != 0)

  918. dir1 = dir1 -> next;

  919. if(dir1 != NULL)

  920. {

  921. printf("create failed,this dir name has been used.\n");

  922. return ;

  923. }

  924. dir = getMemory(struct MULU);

  925. strcpy(dir->dirname,command_str[1]); //新创建的目录名字

  926. dir->link = NULL; //新创建的目录包含的子目录的暂时未空

  927. dir->link1=NULL; //新创建的目录包含的文件暂时为空

  928. dir->pre=nowWorkDir; //新创建的目录的父目录为当前工作目录

  929. link_dir(dir); //对当前工作目录所包含的同级子目录进行链接

  930. }

  931. int find_son_dir(char *dirName) //寻找子目录

  932. {

  933. struct MULU *tmp;

  934. tmp = nowWorkDir->link; //指向当前目录的第一个子目录

  935. while(tmp && strcmp(tmp->dirname, dirName))

  936. {

  937. tmp = tmp->next;

  938. }

  939. if(tmp != NULL)

  940. {

  941. nowWorkDir = tmp; //当前工作目录为这个子目录

  942. sprintf(absolute_path,"%s%s%c",absolute_path,dirName,'/'); //绝对路径

  943. sprintf(relative_path,"%s",dirName); //相对路径

  944. sprintf(mesg,"zhangxiaobai@%s %s$ ",relative_path,username);

  945. return 0;

  946. }

  947. else

  948. return -1;

  949. }

  950. void cut_path(char *dirname)

  951. {

  952. size_t len_abs = strlen(absolute_path);

  953. size_t len_dir = strlen(dirname);

  954. absolute_path[len_abs - 1 - len_dir] = '\0';

  955. }

  956. void cd(void)//切换当前目录

  957. {

  958. int result = -1;

  959. if((strcmp(command, "cd") == 0) || (strcmp(command, "cd ") == 0)) //如果只输入cd 而不输入路径

  960. return ;

  961. else if(command_str[1][0] == '/') //判断路径是不是/ 如果是的话,那就是用户根路径

  962. {

  963. nowWorkDir = nowMainDir->link; //指回用户根目录

  964. sprintf(absolute_path,"/"); //绝对路径

  965. sprintf(relative_path,"/"); //相对路径

  966. sprintf(mesg,"zhangxiaobai@%s %s$ ",relative_path,username);

  967. }

  968. else if(strstr(command_str[1],"..") != NULL) //判断是否是回到上级目录

  969. {

  970. if(nowWorkDir->pre) //如果不是用户根目录的话,那么他有父目录,如果是根目录,则默认不能再返回到上层了

  971. {

  972. nowWorkDir = nowWorkDir->pre;

  973. if(nowWorkDir->pre)

  974. {

  975. cut_path(nowWorkDir->dirname); //绝对路径

  976. sprintf(relative_path,"%s",nowWorkDir->dirname); //相对路径

  977. sprintf(mesg,"zhangxiaobai@%s %s$ ",relative_path,username);

  978. }

  979. else

  980. {

  981. sprintf(absolute_path,"/"); //绝对路径

  982. sprintf(relative_path,"%c",'/'); //相对路径

  983. sprintf(mesg,"zhangxiaobai@%s %s$ ",relative_path,username);

  984. }

  985. }

  986. }

  987. else //不是回到用户根目录,也不是回到上层目录,那么只能是进入子目录中

  988. {

  989. result = find_son_dir(command_str[1]); //寻找子目录

  990. if(result == -1) //找不到子目录

  991. printf("no such a directory\n");

  992. }

  993. }