linux文件系统模拟


  1. #include"stdio.h"
  2. #include<stdlib.h>
  3. //#include<conio.h>
  4. #include<string.h>
  5. #include"unistd.h"
  6. intphysic[100];//文件地址缓冲区
  7. intstyle=1;//文件的类型
  8. charcur_dir[10]="root";//当前目录
  9. structcommand
  10. {
  11. charcom[10];
  12. }cmd[12];
  13. structblock
  14. {
  15. intn;//空闲的盘快的个数
  16. intfree[50];//存放空闲盘快的地址
  17. inta;//模拟盘快是否被占用
  18. }memory[20449];
  19. structblock_super
  20. {
  21. intn;//空闲的盘快的个数
  22. intfree[50];//存放进入栈中的空闲块
  23. intstack[50];//存放下一组空闲盘快的地址
  24. }super_block;
  25. structnode//i结点信息
  26. {
  27. intfile_style;//i结点文件类型
  28. intfile_length;//i结点文件长度
  29. intfile_address[100];//i结点文件的物理地址
  30. }i_node[640];
  31. structdir//目录项信息
  32. {
  33. charfile_name[10];//文件名
  34. inti_num;//文件的结点号
  35. chardir_name[10];//文件所在的目录
  36. }root[640];
  37. voidformat()//格式化
  38. {
  39. inti,j,k;
  40. super_block.n=50;
  41. for(i=0;i<50;i++)//超级块初始化
  42. {
  43. super_block.free[i]=i;//存放进入栈中的空闲块
  44. super_block.stack[i]=50+i;//存放下一组的盘块
  45. }
  46. for(i=0;i<640;i++)//i结点信息初始化
  47. {
  48. for(j=0;j<100;j++)
  49. {
  50. i_node[i].file_address[j]=-1;//文件地址
  51. }
  52. i_node[i].file_length=-1;//文件长度
  53. i_node[i].file_style=-1;//文件类型
  54. }
  55. for(i=0;i<640;i++)//根目录区信息初始化
  56. {
  57. strcpy(root[i].file_name,"");
  58. root[i].i_num=-1;
  59. strcpy(root[i].dir_name,"");
  60. }
  61. for(i=0;i<20449;i++)//存储空间初始化
  62. {
  63. memory[i].n=0;//必须有这个
  64. memory[i].a=0;
  65. for(j=0;j<50;j++)
  66. {
  67. memory[i].free[j]=-1;
  68. }
  69. }
  70. for(i=0;i<20449;i++)//将空闲块的信息用成组链接的方法写进每组的最后一个块中
  71. {//存储空间初始化
  72. if((i+1)%50==0)
  73. {
  74. k=i+1;
  75. for(j=0;j<50;j++)
  76. {
  77. if(k<20450)
  78. {
  79. memory[i].free[j]=k;//下一组空闲地址
  80. memory[i].n++;//下一组空闲个数注意在memory[i].n++之前要给其赋初值
  81. k++;
  82. }
  83. else
  84. {
  85. memory[i].free[j]=-1;
  86. }
  87. }
  88. memory[i].a=0;//标记为没有使用
  89. continue;//处理完用于存储下一组盘块信息的特殊盘块后,跳过本次循环
  90. }
  91. for(j=0;j<50;j++)
  92. {
  93. memory[i].free[j]=-1;
  94. }
  95. memory[i].n=0;
  96. }
  97. printf("已经初始化完毕\n");
  98. printf("进入linux文件系统模拟............\n");
  99. }
  100. voidwrite_file(FILE*fp)//将信息读入系统文件中
  101. {
  102. inti;
  103. fp=fopen("system","wb");
  104. for(i=0;i<20449;i++)
  105. {
  106. fwrite(&memory[i],sizeof(structblock),1,fp);
  107. }
  108. fwrite(&super_block,sizeof(structblock_super),1,fp);
  109. for(i=0;i<640;i++)
  110. {
  111. fwrite(&i_node[i],sizeof(structnode),1,fp);
  112. }
  113. for(i=0;i<640;i++)
  114. {
  115. fwrite(&root[i],sizeof(structdir),1,fp);
  116. }
  117. fclose(fp);
  118. }
  119. voidread_file(FILE*fp)//读出系统文件的信息
  120. {
  121. inti;
  122. fp=fopen("system","rb");
  123. for(i=0;i<20449;i++)
  124. {
  125. fread(&memory[i],sizeof(structblock),1,fp);
  126. }
  127. fread(&super_block,sizeof(structblock_super),1,fp);
  128. for(i=0;i<640;i++)
  129. {
  130. fread(&i_node[i],sizeof(structnode),1,fp);
  131. }
  132. for(i=0;i<640;i++)
  133. {
  134. fread(&root[i],sizeof(structdir),1,fp);
  135. }
  136. fclose(fp);
  137. }
  138. voidcallback(intlength)//回收磁盘空间
  139. {
  140. inti,j,k,m,q=0;
  141. for(i=length-1;i>=0;i--)
  142. {
  143. k=physic[i];//需要提供要回收的文件的地址
  144. m=49-super_block.n;//回收到栈中的哪个位置
  145. if(super_block.n==50)//注意当super_block.n==50时m=-1;的值
  146. {//super_block.n==50的时候栈满了,要将这个栈中的所有地址信息写进下一个地址中
  147. for(j=0;j<50;j++)
  148. {
  149. memory[k].free[j]=super_block.free[j];
  150. }
  151. super_block.n=0;
  152. memory[k].n=50;
  153. }
  154. memory[k].a=0;
  155. if(m==-1)
  156. {
  157. m=49;//将下一个文件地址中的盘块号回收到栈底中,这个地址中存放着刚才满栈的地址的信息
  158. }
  159. super_block.free[m]=physic[i];//将下一个文件地址中的盘块号回收到栈中
  160. super_block.n++;
  161. }
  162. }
  163. voidallot(intlength)//分配空间
  164. {
  165. inti,j,k,m,p;
  166. for(i=0;i<length;i++)
  167. {
  168. k=50-super_block.n;//超级块中表示空闲块的指针
  169. m=super_block.free[k];//栈中的相应盘块的地址
  170. p=super_block.free[49];//栈中的最后一个盘块指向的地址
  171. if(m==-1||memory[p].a==1)//检测是否还有下一组盘块
  172. {
  173. printf("内存不足,不能够分配空间\n");
  174. callback(length);
  175. break;
  176. }
  177. if(super_block.n==1)
  178. {
  179. memory[m].a=1;//将最后一个盘块分配掉
  180. physic[i]=m;
  181. super_block.n=0;
  182. for(j=0;j<memory[m].n;j++)//从最后一个盘块中取出下一组盘块号写入栈中
  183. {
  184. super_block.free[j]=memory[m].free[j];
  185. super_block.n++;
  186. }
  187. continue;//要跳过这次循环,下面的语句在IF中已经执行过
  188. }
  189. physic[i]=m;//栈中的相应盘块的地址写进文件地址缓冲区
  190. memory[m].a=1;
  191. super_block.n--;
  192. }
  193. }
  194. voidcreate_file(charfilename[],intlength)//创建文件
  195. {
  196. inti,j;
  197. for(i=0;i<640;i++)
  198. {
  199. if(strcmp(filename,root[i].file_name)==0)
  200. {
  201. printf("文件已经存在,不允许建立重名的文件\n");
  202. return;
  203. }
  204. }
  205. for(i=0;i<640;i++)
  206. {
  207. if(root[i].i_num==-1)
  208. {
  209. root[i].i_num=i;
  210. strcpy(root[i].file_name,filename);
  211. strcpy(root[i].dir_name,cur_dir);//把当前目录名给新建立的文件
  212. i_node[i].file_style=style;
  213. i_node[i].file_length=length;
  214. allot(length);
  215. for(j=0;j<length;j++)
  216. {
  217. i_node[i].file_address[j]=physic[j];
  218. }
  219. break;
  220. }
  221. }
  222. }
  223. voidcreate_dir(charfilename[])//创建目录
  224. {
  225. style=0;//0代表文件类型是目录文件
  226. create_file(filename,4);
  227. style=1;//用完恢复初值,因为全局变量,否则
  228. }
  229. voiddel_file(charfilename[])//删除文件
  230. {
  231. inti,j,k;
  232. for(i=0;i<640;i++)
  233. {
  234. if(strcmp(filename,root[i].file_name)==0)
  235. {
  236. k=root[i].i_num;
  237. for(j=0;j<i_node[k].file_length;j++)
  238. {
  239. physic[j]=i_node[k].file_address[j];
  240. }
  241. callback(i_node[k].file_length);//调用回收函数
  242. for(j=0;j<100;j++)//删除文件后要将文件属性和目录项的各个值恢复初值
  243. {
  244. i_node[k].file_address[j]=-1;//地址恢复初值
  245. }
  246. strcpy(root[i].file_name,"");//文件名恢复初值
  247. root[i].i_num=-1;//目录项的I结点信息恢复初值
  248. strcpy(root[i].dir_name,"");//目录项的文件目录信息恢复初值
  249. i_node[k].file_length=-1;//文件长度恢复
  250. i_node[k].file_style=-1;//文件类型恢复初值
  251. break;
  252. }
  253. }
  254. if(i==640)
  255. {
  256. printf("不存在这个文件\n");
  257. }
  258. }
  259. voiddel_dir(charfilename[])//删除目录需要判断目录下时候为空,不为空就不删除
  260. {
  261. inti,j,k;
  262. for(i=0;i<640;i++)//还要加条件判断要删除的目录是不是当前目录
  263. {
  264. k=root[i].i_num;//找到目录名字
  265. if(strcmp(root[i].file_name,filename)==0&&strcmp(cur_dir,filename)!=0&&(i_node[k].file_style)==0)
  266. {
  267. for(j=0;j<640;j++)
  268. {
  269. if(strcmp(filename,root[j].dir_name)==0)
  270. {
  271. printf("目录不为空不能直接删除\n");
  272. break;
  273. }
  274. }
  275. if(j==640)
  276. {
  277. del_file(filename);
  278. break;
  279. }
  280. break;
  281. }
  282. }
  283. if(i==640)
  284. {
  285. printf("这个不是目录文件或者不存在这个目录,或者你要删除的是当前目录\n");
  286. }
  287. }
  288. voiddisplay_curdir()//显示当前目录下的文件列表
  289. {
  290. inti,k;
  291. printf("\t\t文件名字文件类型文件长度所属目录\n");
  292. for(i=0;i<640;i++)
  293. {
  294. if(strcmp(cur_dir,root[i].dir_name)==0)//查询文件中所在目录信息和当前目录信息相同的数据
  295. {
  296. k=root[i].i_num;
  297. printf("\t\t%s\t",root[i].file_name);//文件名
  298. printf("\t%d\t",i_node[k].file_style);//文件的类型
  299. printf("%d\t",i_node[k].file_length);//文件的长度
  300. printf("%s\n",root[i].dir_name);//文件所在的目录
  301. }
  302. }
  303. }
  304. voiddisplay_dir(charfilename[])//进入指定的目录
  305. {
  306. inti,k;
  307. for(i=0;i<640;i++)
  308. {
  309. k=root[i].i_num;//判断文件类型是不是目录类型
  310. if((strcmp(filename,root[i].file_name)==0)&&(i_node[k].file_style==0))
  311. {
  312. strcpy(cur_dir,filename);//将要进入的指定目录设置为当前目录赋值不要反了strcpy(目的,源)
  313. break;
  314. }
  315. }
  316. if(i==640)
  317. {
  318. printf("没有这个目录\n");
  319. }
  320. }
  321. voidopen_file(charfilename[])//打开文件
  322. {
  323. inti,j,k;
  324. printf("\t\t文件名字文件类型文件长度所属目录\n");
  325. for(i=0;i<640;i++)
  326. {
  327. k=root[i].i_num;
  328. if(strcmp(filename,root[i].file_name)==0&&(i_node[k].file_style==1))
  329. {
  330. printf("\t\t%s\t",root[i].file_name);//文件名
  331. printf("\t%d\t",i_node[k].file_style);//文件的类型
  332. printf("%d\t",i_node[k].file_length);//文件的长度
  333. printf("%s\n",root[i].dir_name);//文件所在的目录
  334. printf("\t\t文件占用的物理地址\n");
  335. for(j=0;j<i_node[k].file_length;j++)//显示物理地址
  336. {
  337. printf("%d",i_node[k].file_address[j]);//文件具体占用的盘块号
  338. }
  339. printf("\n");
  340. break;
  341. }
  342. }
  343. if(i==640)
  344. {
  345. printf("没有这个文件或者这个文件不是正规文件\n");
  346. }
  347. }
  348. voidback_dir()//返回上一级目录
  349. {
  350. inti,k;
  351. for(i=0;i<640;i++)//查询和当前目录名相同的目录文件名
  352. {
  353. k=root[i].i_num;
  354. if(strcmp(cur_dir,root[i].file_name)==0&&(i_node[k].file_style==0))
  355. {
  356. strcpy(cur_dir,root[i].dir_name);//将查询到的目录文件名所在的目录赋值给当前目录
  357. }
  358. }
  359. }
  360. voiddisplay_sys()//显示系统信息(磁盘使用情况)
  361. {
  362. inti,m,k=0;
  363. for(i=0;i<20449;i++)
  364. {
  365. if(memory[i].a==0)
  366. k++;
  367. }
  368. m=20449-k;
  369. printf("空闲的盘块数是:\t");
  370. printf("%d\n",k);
  371. printf("使用的盘块数是:\t");
  372. printf("%d\n",m);
  373. }
  374. voidhelp()//显示帮助信息
  375. {
  376. printf("注意:创建的文件长度<100\n\n");//说明文件
  377. printf("0.初始化-------------------------format\n");
  378. printf("1.查看当前目录文件列表-----------dir\n");
  379. printf("2.创建文件---------------------create-----(create+空格+文件名+文件长度)\n");
  380. printf("3.打开文件-----------------------cat-----(cat+空格+文件名)\n");
  381. printf("4.删除文件-----------------------del-----(del+空格+文件名)\n");
  382. printf("5.创建目录-----------------------md------(md+空格+目录名)\n");
  383. printf("6.删除目录-----------------------deldir--(del+空格+目录名)\n");
  384. printf("7.进入当前目录下的指定目录-------cd--------(cd+空格+目录名)\n");
  385. printf("8.返回上一级目录-----------------cd..\n");
  386. printf("9.查看系统信息-------------------ls\n");
  387. printf("10.显示帮助命令-----------------help\n");
  388. printf("11.退出文件模拟------------------exit\n");
  389. }
  390. voidmain()//主函数
  391. {
  392. chartmp[10],com[10],tmp1[10],k;
  393. structcommandtmp2[10];
  394. inti,j=0,p,len=0;
  395. FILE*fp;
  396. help();
  397. strcpy(cmd[0].com,"format");//将各个命令存进命令表
  398. strcpy(cmd[1].com,"dir");
  399. strcpy(cmd[2].com,"cat");
  400. strcpy(cmd[3].com,"ls");
  401. strcpy(cmd[4].com,"md");
  402. strcpy(cmd[5].com,"create");
  403. strcpy(cmd[6].com,"del");
  404. strcpy(cmd[7].com,"deldir");
  405. strcpy(cmd[8].com,"cd");
  406. strcpy(cmd[9].com,"cd..");
  407. strcpy(cmd[10].com,"help");
  408. strcpy(cmd[11].com,"exit");
  409. if((fp=fopen("system","rb"))==NULL)//判断系统文件是否存在
  410. {
  411. printf("cannotopenfile\n");
  412. printf("formatthediskY/N\n");
  413. scanf("%c",&k);
  414. if(k=='y')
  415. format();
  416. }
  417. else
  418. {
  419. read_file(fp);//读取系统文件的内容
  420. }
  421. while(1)
  422. {
  423. j=0;//必须重新给恢复0否则出错
  424. strcpy(tmp,cur_dir);
  425. while(strcmp(tmp,"root")!=0)
  426. {
  427. for(i=0;i<640;i++)
  428. {
  429. p=root[i].i_num;
  430. if(strcmp(tmp,root[i].file_name)==0&&(i_node[p].file_style==0))
  431. {
  432. strcpy(tmp2[j].com,tmp);
  433. j++;
  434. strcpy(tmp,root[i].dir_name);
  435. }
  436. }
  437. }
  438. strcpy(tmp2[j].com,tmp);
  439. for(i=j;i>=0;i--)
  440. {
  441. printf("%s/",tmp2[i].com);
  442. }
  443. scanf("%s",com);//输入命令并且查找命令的相关操作
  444. for(i=0;i<12;i++)
  445. {
  446. if(strcmp(com,cmd[i].com)==0)
  447. {
  448. p=i;
  449. break;
  450. }
  451. }
  452. if(i==12)//如果没有这个语句以后输入的命令都和第一次输入的效果一样
  453. {
  454. p=13;//随便的一个值
  455. }
  456. switch(p)
  457. {
  458. case0:format();//初始化
  459. break;
  460. case1:display_curdir();//查看当前目录下的文件列表
  461. break;
  462. case2:scanf("%s",tmp);//查看文件
  463. open_file(tmp);
  464. break;
  465. case3:display_sys();//查看系统信息
  466. break;
  467. case4:scanf("%s",tmp);//创建目录
  468. create_dir(tmp);
  469. break;
  470. case5:scanf("%s",tmp);//创建文件
  471. scanf("%d",&len);
  472. create_file(tmp,len);
  473. break;
  474. case6:scanf("%s",tmp);//删除文件
  475. for(i=0;i<640;i++)//判断文件是不是正规文件
  476. {
  477. j=root[i].i_num;
  478. if(strcmp(tmp,root[i].file_name)==0&&(i_node[j].file_style)==1)
  479. {
  480. del_file(tmp);
  481. break;
  482. }
  483. }
  484. if(i==640)
  485. {
  486. printf("这个不是正规文件文件\n");
  487. }
  488. break;
  489. case7:
  490. scanf("%s",tmp);//删除目录
  491. del_dir(tmp);
  492. break;
  493. case8:scanf("%s",tmp1);//进入当前目录下的指定目录相当于进入目录cd+目录名
  494. display_dir(tmp1);
  495. break;
  496. case9:back_dir();//返回上一级目录
  497. break;
  498. case10:help();
  499. break;
  500. case11:write_file(fp);//将磁盘利用信息写进系统文件,退出
  501. return;
  502. default:printf("没有这个命令\n");
  503. break;
  504. }
  505. }
  506. }

linux文件系统模拟