操作系统课程设计为LINUX设计一个简单的二级文件系统.docx
《操作系统课程设计为LINUX设计一个简单的二级文件系统.docx》由会员分享,可在线阅读,更多相关《操作系统课程设计为LINUX设计一个简单的二级文件系统.docx(22页珍藏版)》请在冰豆网上搜索。
操作系统课程设计为LINUX设计一个简单的二级文件系统
设计题目:
为LINUX设计一个简单的二级文件系统
设计目的:
1、通过一个简单多用户文件系统的设计,加深理解文件系统的内部功能及内部实现。
2、提高学生的程序设计能力、提高算法设计质量与程序设计素质。
设计任务:
(在规定的时间内完成下列任务)
为LINUX设计一个简单的二级文件系统。
要求做到以下几点:
1、可以实现下列几条命令(至少4条)
Login
用户登录
Dir
列文件目录
Create
创建文件
Delete
删除文件
Open
打开文件
Close
关闭文件
Read
读文件
Write
写文件
2、列目录时要列出文件名、物理地址、保护码和文件长度。
3、源文件可以进行读写保护。
时间安排:
1月17日布置课程设计任务;分配题目后,查阅资料、准备程序;
1月18日~1月20日上机调试程序、书写课程设计报告;
1月21日上午提交课程设计报告及相关文档。
地点:
学校机房(具体见现代教育中心大屏幕安排)
具体要求:
1、课程设计报告按统一通用格式书写,具体格式要求请在网络上查阅
2、每位学生应独立完成各自的任务且每天至少在设计室工作半天
指导教师签名:
11年1月7日
教研室主任(或责任教师)签名:
11年1月7日
一.项目概述
Linux是一个性能稳定、功能强大、效率高的操作系统。
它在功能特性方面与Unix系统相似,同时又具有多任务、多用户、多平台等若干特性。
Linux的源代码是开放的,阅读Linux源代码,无疑是深入学习Linux的最好方法。
文件系统是Linux操作系统的重要组成部分,Linux文件具有强大的功能。
文件系统中的文件是数据的集合,文件系统不仅包含着文件中的数据而且还有文件系统的结构,所有Linux用户和程序看到的文件、目录、软连接及文件保护信息等都存储在其中。
二.课程设计设计题目
课程设计题目:
Linux二级文件系统设计
三.开发语言及实现平台或实验环境
开发语言:
C++/VC++
实现平台(环境):
visualC++、windowxp、VMwareWorkstation(虚拟机)V6.0.2、RedHatEnterpriseLinuxos、office2003
四.设计目的
(1)本实验的目的是通过一个简单多用户文件系统的设计,加深理解文件系统的内部功能和内部实现。
(2)结合数据结构、程序设计、计算机原理等课程的知识,设计一个二级文件系统,进一步理解操作系统。
(3)通过分对实际问题的分析、设计、编程实现,提高学生实际应用、编程的能力
五.设计内容
5.1.任务
为Linux系统设计一个简单的二级文件系统。
要求做到以下几点:
1.可以实现下列几条命令:
login用户登录
dir列目录
create创建文件
delete删除文件
open打开文件
close关闭文件
read读文件
write写文件
cd进出目录
2.列目录时要列出文件名,物理地址,保护码和文件长度
3.源文件可以进行读写保护
5.2.主程序流程图
六.程序设计
6.1.设计思想
本文件系统采用两级目录,其中第一级对应于用户账号,第二级对应于用户帐号下的文件。
另外,为了简便文件系统未考虑文件共享,文件系统安全以及管道文件与设备文件等特殊内容。
首先应确定文件系统的数据结构:
主目录、子目录及活动文件等。
主目录和子目录都以文件的形式存放于磁盘,这样便于查找和修改。
用户创建的文件,可以编号存储于磁盘上。
如:
file0,file1,file2…并以编号作为物理地址,在目录中进行登记。
6.2.设计要求
理解Linux的文件系统的组织;掌握常用的数据结构;系统采用两级目录,其中第一级对应于用户账号,第二级对应于用户帐号下的文件;使用文件来模拟外存,进行数据结构设计和操作算法的设计,实现一个文件系统并实现基本的文件操作(为了简便文件系统,不考虑文件共享,文件系统安全以及管道文件与设备文件等特殊内容)。
要求:
1、对程序的每一部分要有详细的设计分析说明
2、程序执行的每个步骤要有具体的提示内容或输出
3、源代码格式规范,注释不少于三分之一
4、设计合适的测试用例,对得到的运行结果要有分析,
5、设计中遇到的问题,设计的心得体会
6、提交完整程序代码、课程设计报告及相关文档
七.设计原理
7.1.外存管理
文件系统是一个含有大量的文件及其属性,对文件进行操作、管理的软件,以及向用户提供使用文件的接口的一个集合。
在逻辑上它的层次结构是这样的:
文件系统接口
对对象的操作和管理的软件集合
逻辑文件系统
基本I/O管理程序(文件组织模块)
基本文件系统(物理I/O层)
I/O控制层(设备驱动程序)
对象及其属性说明
作为产品的操作系统有各自的文件系统。
比如MS的WINDOWS系列使用的是FAT16、FAT32或NTFS的文件系统、LINUX使用的是EXT2、EXT3文件系统等等。
7.2.linux的EXT2文件系统
linux使用一个叫虚拟文件系统的技术从而可以支持多达几十种的不同文件系统,而EXT2是linux自己的文件系统。
它有几个重要的数据结构,一个是超级块,用来描述目录和文件在磁盘上的物理位置、文件大小和结构等信息。
inode也是一个重要的数据结构。
文件系统中的每个目录和文件均由一个inode描述。
它包含:
文件模式(类型和存取权限)、数据块位置等信息。
如果希望详细学习EXT2文件系统可以参看linux内核代码include/linux/ext2_fs.h、include/linux/ext2_fs_sb.h等文件。
一个文件系统除了重要的数据结构之外,还必须为用户提供有效的接口操作。
比如EXT2提供的OPEN/CLOSE接口操作。
7.3.用内存来模拟外存
真正的文件系统对外存进行管理,涉及到许多硬件、设备管理方面的底层技术,一方面这些技术不属于操作系统核心内容,一方面过多的内容不免造成实验者顾此失彼,所以这里推荐一种使用内存来模拟外存的方式,可以跳过这些硬件技术而直接把精力放在数据结构设计和操作算法设计上面。
假定pInode是一个指向inode结构的指针,而且它已经放入的需要放入的数值了,现在需要将其写入到特定位置。
可用如下代码:
……
fd=fopen(“filesystem”,”w+b”);//fd是FILE指针类型,w便是写方式,b表示二进制
fseek(fd,specific_area,SEEK_SET);//fd是文件指针;specific_area为整形,
//为需要入pInode的位置
fwrite(pInode,1,sizeof(inode),fd);//写入pInode信息
7.4.编码
#include
#include
#include
#defineDIR_LENGTH1024/*路径最长可达100字节*/
#defineMAX_WRITE1024*128/*写入文字可达128k字节*/
#defineMEM_D_SIZE1024*1024/*1M磁盘空间*/
#defineDISKSIZE1024/*磁盘块的大小1K*/
#defineMSD5/*最大子目录数5*/
#defineDISK_NUMMEM_D_SIZE/DISKSIZE/*磁盘块数目1024=1M/1K*/
#defineFATSIZEDISK_NUM*sizeof(structfatitem)/*FAT表大小*/
#defineMOFN5/*最大文件打开数5(即除根以外最大深度为5)*/
#defineROOT_DISK_NOFATSIZE/DISKSIZE+1/*根目录起始盘快号9*/
#defineROOT_DISK_SIZEsizeof(structdirect)/*根目录大小196*/
/*---------------FAT表项结构-----------------------*/
structfatitem/*size8*/
{
intitem;/*存放文件下一个磁盘的指针*/
charem_disk;/*磁盘块是否空闲标志位0空闲*/
};
/*-------------------目录项结构------------------------*/
structdirect
{
/*-----文件控制快信息-----*/
structFCB
{
charname[9];/*文件/目录名8位*/
charproperty;/*属性1位目录0位普通文件*/
intsize;/*文件/目录字节数、盘块数)*/
intfirstdisk;/*文件/目录起始盘块号*/
intnext;/*子目录起始盘块号*/
intsign;/*1是根目录0不是根目录*/
}directitem[MSD+2];
};
/*------------------文件打开表项结构--------------------------*/
structopentable
{
structopenttableitem
{
charname[9];/*文件名*/
intfirstdisk;/*起始盘块号*/
intsize;/*文件的大小*/
}openitem[MOFN];
intcur_size;/*当前打文件的数目*/
};
/*-------------------------------------------------------------------*/
structfatitem*fat;/*FAT表*/
structdirect*root;/*根目录*/
structdirect*cur_dir;/*当前目录*/
structopentableu_opentable;/*文件打开表*/
intfd=-1;/*文件打开表的序号*/
char*bufferdir;/*记录当前路径的名称*/
char*fdisk;/*虚拟磁盘起始地址*/
intcreate(char*name);
intopen(char*name);
intclose(char*name);
intwrite(intfd,char*buf,intlen);
intread(intfd,char*buf);
intdel(char*name);
intmkdir(char*name);
intrmdir(char*name);
voiddir();
intcd(char*name);
/*-----------创建文件---------------------------------*/
intcreate(char*name)
{
inti,j;
if(strlen(name)>8)/*文件名大于8位*/
return(-1);
for(j=2;j{
if(!
strcmp(cur_dir->directitem[j].name,name))
break;
}
if(jreturn(-4);
for(i=2;i{
if(cur_dir->directitem[i].firstdisk==-1)
break;
}
if(i>=MSD+2)/*无空目录项*/
return(-2);
if(u_opentable.cur_size>=MOFN)/*打开文件太多*/
return(-3);
for(j=ROOT_DISK_NO+1;j{
if(fat[j].em_disk=='0')
break;
}
if(j>=DISK_NUM)
return(-5);
fat[j].em_disk='1';/*将空闲块置为已经分配*/
/*-----------填写目录项-----------------*/
strcpy(cur_dir->directitem[i].name,name);
cur_dir->directitem[i].firstdisk=j;
cur_dir->directitem[i].size=0;
cur_dir->directitem[i].next=j;
cur_dir->directitem[i].property='0';
/*---------------------------------*/
fd=open(name);
return0;
/*---------打开文件---------------------------*/
intopen(char*name)
{
inti,j;
for(i=2;i{
if(!
strcmp(cur_dir->directitem[i].name,name))
break;
}
if(i>=MSD+2)
return(-1);
/*--------是文件还是目录-----------------------*/
if(cur_dir->directitem[i].property=='1')
return(-4);
/*--------文件是否打开-----------------------*/
for(j=0;j{
if(!
strcmp(u_opentable.openitem[j].name,name))
break;
}
if(jreturn(-2);
if(u_opentable.cur_size>=MOFN)/*文件打开太多*/
return(-3);
/*--------查找一个空闲用户打开表项-----------------------*/
for(j=0;j{
if(u_opentable.openitem[j].firstdisk==-1)
break;
}
/*--------------填写表项的相关信息------------------------*/
u_opentable.openitem[j].firstdisk=cur_dir->directitem[i].firstdisk;
strcpy(u_opentable.openitem[j].name,name);
u_opentable.openitem[j].size=cur_dir->directitem[i].size;
u_opentable.cur_size++;
/*----------返回用户打开表表项的序号--------------------------*/
return(j);
}
/*-----------关闭文件------------------------*/
intclose(char*name)
{
inti;
for(i=0;i{if(!
strcmp(u_opentable.openitem[i].name,name))
break;
}
if(i>=MOFN)return(-1);
/*----清空该文件的用户打开表项的内容---------------------*/
strcpy(u_opentable.openitem[i].name,"");
u_opentable.openitem[i].firstdisk=-1;
u_opentable.openitem[i].size=0;
u_opentable.cur_size--;
return0;
}
/*---------写文件---------------------------*/
intwrite(intfd,char*buf,intlen)
{
char*first;
intitem,i,j,k;
intilen1,ilen2,modlen,temp;
/*---用$字符作为空格#字符作为换行符------------------*/
charSpace=32;
charEndter='\n';
for(i=0;i{if(buf[i]=='$')
buf[i]=Space;
elseif(buf[i]=='#')
buf[i]=Endter;
}
/*----读取用户打开表对应表项第一个盘块号----------*/
item=u_opentable.openitem[fd].firstdisk;
/*--找到当前目录所对应表项的序号--------------*/
for(i=2;i{
if(cur_dir->directitem[i].firstdisk==item)
break;
}
temp=i;/*-存放当前目录项的下标-*/
/*------找到的item是该文件的最后一块磁盘块-------------------*/
while(fat[item].item!
=-1)
{
item=fat[item].item;/*-查找该文件的下一盘块--*/
}
/*-----计算出该文件的最末地址-------*/
first=fdisk+item*DISKSIZE+u_opentable.openitem[fd].size%DISKSIZE;
/*-----如果最后磁盘块剩余的大小大于要写入的文件的大小-------*/
if(DISKSIZE-u_opentable.openitem[fd].size%DISKSIZE>len)
{
strcpy(first,buf);
u_opentable.openitem[fd].size=u_opentable.openitem[fd].size+len;
cur_dir->directitem[temp].size=cur_dir->directitem[temp].size+len;
}
else
{
for(i=0;i<(DISKSIZE-u_opentable.openitem[fd].size%DISKSIZE);i++)
{/*写一部分内容到最后一块磁盘块的剩余空间(字节)*/
first[i]=buf[i];
}
/*计算分配完最后一块磁盘的剩余空间(字节)还剩下多少字节未存储*/
ilen1=len-(DISKSIZE-u_opentable.openitem[fd].size%DISKSIZE);
ilen2=ilen1/DISKSIZE;
modlen=ilen1%DISKSIZE;
if(modlen>0)
ilen2=ilen2+1;/*--还需要多少块磁盘块-*/
for(j=0;j{
for(i=ROOT_DISK_NO+1;i{
if(fat[i].em_disk=='0')
break;
}
if(i>=DISK_NUM)/*--如果磁盘块已经分配完了-*/
return(-1);
first=fdisk+i*DISKSIZE;/*--找到的那块空闲磁盘块的起始地址-*/
if(j==ilen2-1)/*--如果是最后要分配的一块-*/{for(k=0;kfirst[k]=buf[k];
}
else/*-如果不是要最后分配的一块--*/
{
for(k=0;kfirst[k]=buf[k];
}
fat[item].item=i;/*--找到一块后将它的序号存放在上一块的指针中-*/
fat[i].em_disk='1';/*--置找到的磁盘快的空闲标志位为已分配-*/
fat[i].item=-1;/*--它的指针为-1(即没有下一块)-*/
}
/*--修改长度-*/
u_opentable.openitem[fd].size=u_opentable.openitem[fd].size+len;
cur_dir->directitem[temp].size=cur_dir->directitem[temp].size+len;
}
return0;
}
/*----------读文件--------------------*/
intread(intfd,char*buf)
{
intlen=u_opentable.openitem[fd].size;
char*first;
inti,j,item;
intilen1,modlen;
item=u_opentable.openitem[fd].firstdisk;
ilen1=len/DISKSIZE;
modlen=len%DISKSIZE;
if(modlen!
=0)
ilen1=ilen1+1;/*--计算文件所占磁盘的块数-*/
first=fdisk+item*DISKSIZE;/*--计算文件的起始位置-*/
for(i=0;i{
if(i==ilen1-1)/*--如果在最后一个磁盘块-*/
{
for(j=