操作系统4.docx
- 文档编号:11453738
- 上传时间:2023-03-01
- 格式:DOCX
- 页数:36
- 大小:67.24KB
操作系统4.docx
《操作系统4.docx》由会员分享,可在线阅读,更多相关《操作系统4.docx(36页珍藏版)》请在冰豆网上搜索。
操作系统4
实验原理
文件系统指文件存在的物理空间,Linux系统中每个分区都是一个文件系统,都有自己的目录层次结构。
Linux会将这些分属不同分区的、单独的文件系统按一定的方式形成一个系统的总的目录层次结构。
一个操作系统的运行离不开对文件的操作,因此必然要拥有并维护自己的文件系统。
Linux文件系统使用索引节点来记录文件信息,作用像windows的文件分配表。
索引节点是一个结构,它包含了一个文件的长度、创建及修改时间、权限、所属关系、磁盘中的位置等信息。
一个文件系统维护了一个索引节点的数组,每个文件或目录都与索引节点数组中的唯一一个元素对应。
系统给每个索引节点分配了一个号码,也就是该节点在数组中的索引号,称为索引节点号。
Linux文件系统将文件索引节点号和文件名同时保存在目录中。
所以,目录只是将文件的名称和它的索引节点号结合在一起的一张表,目录中每一对文件名称和索引节点号称为一个连接。
对于一个文件来说有唯一的索引节点号与之对应,对于一个索引节点号,却可以有多个文件名与之对应。
因此,在磁盘上的同一个文件可以通过不同的路径去访问它。
可以用ln命令对一个已经存在的文件再建立一个新的连接,而不复制文件的内容。
连接有软连接和硬连接之分,软连接又叫符号连接。
它们各自的特点是:
硬连接:
原文件名和连接文件名都指向相同的物理地址。
目录不能有硬连接;硬连接不能跨越文件系统(不能跨越不同的分区)。
文件在磁盘中只有一个拷贝,节省硬盘空间;由于删除文件要在同一个索引节点属于唯一的连接时才能成功,因此可以防止不必要的误删除。
符号连接:
用ln-s命令建立文件的符号连接。
符号连接是linux特殊文件的一种,作为一个文件,它的数据是它所连接的文件的路径名。
类似windows下的快捷方式。
可以删除原有的文件而保存连接文件,没有防止误删除功能。
接下去我们看看本指导书将要采用的用例―FAT。
作为一种文件名称,FAT(FileAllocationTable,文件分配表)自1981年问世以来,已经成为一个计算机术语。
由于时代的原因,包括Windows、MacOS以及多种Unix版本在内的大多数操作系统均对FAT提供支持。
这是MS-DOS和最早期的Windows95操作系统中使用的磁盘分区格式。
它采用16位的文件分配表,是目前获得操作系统支持最多的一种磁盘分区格式,几乎所有的操作系统都支持这种分区格式,从DOS、Windows95、WindowsOSR2到现在的Windows98、WindowsMe、WindowsNT、Windows2000、WindowsXP都支持FAT16,但只支持2GB的硬盘分区成为了它的一大缺点。
FAT16分区格式的另外一个缺点是:
磁盘利用效率低(具体的技术细节请参阅相关资料)。
为了解决这个问题,微软公司在Windows95OSR2中推出了一种全新的磁盘分区格式——FAT32。
FAT中的每个表项都对应了磁盘中每一块的分配状况,FAT的表项位数决定了最大可表示的磁盘容量。
FAT16表示最多支持216个块(或簇)。
FAT表项的可能值为:
0x00:
表示对应块空闲
0xFF:
表示对应块为文件的最后一块
其它值:
表示该文件的下一块的块号
文件目录里记录了文件的控制信息,每一个目录项(FCB)都对应一个文件,用户要操作文件时总是先查询目录找出FCB,然后才能读取文件内容。
简单文件系统示范:
1、虚拟磁盘结构
#defineMAX_DISK_SIZE256
u_charg_disk[MAX_DISK_SIZE]
定义每一个磁盘块大小为16字节,所以系统最多存放16个物理块内容。
规定FAT表总占用第0块,使用8位的FAT表项,所以第0块共有16个FAT表项,目录表占用第1至4块,每个目录项(FCB)占16个字节,因此系统最多支持4个文件。
由于0~5块被系统占用,FAT的第0~5字节应为0xFF,故系统最大支持块数量为10块。
2、系统数据结构
/*************************************************************
FAT结构
使用1个字节(8位)表示一个块号
cluster值:
0x00:
空闲
0xFF:
文件的最后一块
其它值:
文件的下一块块号
*************************************************************/
typedefstruct_tagfat{
u_charcluster;
}FAT,*PFAT,**PPFAT;
/***********************************************************
文件控制块结构(16字节)
f_name:
文件名,最长8个字符,注意要留一个字符保存’\0’,故文件名最长7个字符
f_size:
文件长度
f_firstblock:
文件的起始块号
********************************************************/
typedefstruct_tagfcb{
charf_name[8];
intf_size;
intf_firstblock;
}FCB,*PFCB,**PPFCB;
3、文件删除原理。
删除一个文件时需要做两件事:
(1)把文件占用的块号对应的FAT项清0x00。
例如被删除的文件占用了第7块物理块,那么要将FAT的第7字节置0x00(原本为0xFF)
(2)把目录表中的相应项中的文件名第一个字节置0xE5
由此看出,使用FAT的文件系统删除文件时并不清除文件占用的物理块内容,这也给反删除文件带来了可能。
在目录项中,文件名的第一个字节很关键,如果是0xE5的话则说明该目录项空闲可以存放一个文件信息,否则说明已被占用。
实验内容
在内存中模拟一简单的文件系统,可以完成文件的创建和索引功能。
问题的描述如下:
1、遵循FAT格式使用内存模拟一个文件系统,并实现以下命令接口:
(1)新建文件,格式:
mkfilefilenamefilecontent
filename:
文件名
filecontent:
文件内容(字符)
实现按FAT格式写FAT表和目录表,以及文件内容。
(2)列出文件,格式:
dir
列出目录里所有的文件信息和虚拟磁盘信息。
(3)显示文件内容,格式:
typefilename
filename:
文件名
在目录项中查找文件名所在块号,并把文件内容打印在屏幕上。
(4)删除文件:
delfilename
filename:
文件名
将文件删除,回收虚拟磁盘空间。
(5)退出文件系统:
quit
2、本指书仅将给出一个文件系统格式范例,同学们可以在此基础上进行改进,如:
可以使用文件来模拟文件系统,可以实现多级的目录结构,模拟ext2格式的Linux文件系统等。
实验代码如下:
#include
#include
#include
#include
#include
usingnamespacestd;
constintBLOCKNUM_SIZE=2;//盘块号大小
constintBLOCK_SIZE=1024;//一个盘块大小数
constintBLOCK_NUM=10001;//盘块数量
constintDISK_SIZE=1024*1000*10;//磁盘大小
constintLIST_SIZE=32;//目录项大小
constintMAP_SIZE=10001;//MAP长度
constintFATNUM=125;//FAT的盘块数第块没有用
constintFATLIST=512;//每个盘口FAT的记录数
constintDATABEG=128;//数据项开始FAT号
structFCB
{
charfname[8];//文件名
charexname[3];//扩展名
shortfnum;//首块号
intlength;//文件大小,目录则文件大小为;
};
structfatid{
shortid[FATNUM*FATLIST];//FAT大小512个记录一块
}*FAT;
structmap{
bitset
}*MAP;
structDIR
{
structFCBlist[LIST_SIZE+1];
}*filedir;
intcurrentid=128;//当前FAT号
intcurrentdir=128;//当前目录块号初始化是+1由于第个单元没有使用
char*file;//磁盘的首地址
char*FilePath="myfat";//window文件保存地址
FILE*fp;//window文件地址
stringCURRENT="root\\";//当前路径
charcmd[30];//输入指令
charcommand[16];
/*
*对文件存储器进行格式化
*创建根目录
*
*/
voidfindBit(structmap*MAP)
{
}
voidinit(structfatid*FAT)
{
inti;
for(i=1;i { if(i>DATABEG) FAT->id[i]=0; else FAT->id[i]=-1; } } voidformat() { FAT=(structfatid*)(file+BLOCK_SIZE);//当前FAT地址 MAP=(structmap*)(file+(FATNUM+1)*BLOCK_SIZE);//初始化位示图 init(FAT); FAT->id[0]=9872; filedir=(structDIR*)(file+(FATNUM+1+2)*BLOCK_SIZE);//当前目录指针地址 FAT->id[128]=-1; FAT->id[0]=9872-1; strcpy(filedir->list[0].fname,"."); strcpy(filedir->list[0].exname,"dir"); filedir->list[0].fnum=currentdir; filedir->list[0].length=0; strcpy(filedir->list[1].fname,".."); strcpy(filedir->list[1].exname,"dir"); filedir->list[1].fnum=currentdir; filedir->list[1].length=0; fp=fopen(FilePath,"w+"); fwrite(file,sizeof(char),DISK_SIZE,fp); fclose(fp); printf("初始化已经完成,现在可以进行操作了! \n\n"); } /* *创建子目录 */ intmkdir(char*str) { inti,j; //将要创建的FAT号 intblockdir;//将要创建的目录块号 //目录块内编号 structfatid*flagid; structDIR*dir;//当前目录指针 structmap*MAP; structfatid*FAT; if(strcmp(str,"")==0) { printf("目录名称不能为空\n"); return0; } dir=(structDIR*)(file+(currentdir)*BLOCK_SIZE); MAP=(structmap*)(file+(FATNUM+1)*BLOCK_SIZE); FAT=(structfatid*)(file+BLOCK_SIZE); for(i=DATABEG+1;i { if(MAP->maplist[i]==0) break; } if(i>BLOCK_NUM) { printf("内存不足\n"); return0; } MAP->maplist[i]=1;//map置即已用 dir=(structDIR*)(file+(currentdir)*BLOCK_SIZE); for(i=2;i { if(strcmp(dir->list[i].fname,str)==0) { printf("目录下有同名文件夹\n"); return0; } } for(i=2;i { if(strcmp(dir->list[i].fname,"")==0)//有空的目录块且无重名,第一版本的时候与上面的循环放在一起,存在一个情况是前面的建立的目录删除后,直接被同名的覆盖了 break; if(i>LIST_SIZE) { printf("内存不足\n"); return0; } } flagid=(structfatid*)(file+BLOCK_SIZE);//fat首位地址 for(j=DATABEG+1;j { if(flagid->id[j]==0) { blockdir=j; break; } } strcpy(dir->list[i].fname,str); dir->list[i].fnum=blockdir; strcpy(dir->list[i].exname,"dir"); dir->list[i].length=0; dir=(structDIR*)(file+blockdir*BLOCK_SIZE);//为新目录项创建根目录 strcpy(dir->list[0].fname,"."); strcpy(dir->list[0].exname,"dir"); dir->list[0].fnum=blockdir; dir->list[0].length=0; strcpy(dir->list[1].fname,".."); strcpy(dir->list[1].exname,"dir"); dir->list[1].fnum=currentdir; dir->list[1].length=0; flagid->id[j]=-1;//修改FAT目录尾部 FAT->id[0]=FAT->id[0]-1; printf("已经成功创建目录%s\n",str); return0; } /* *显示目录 */ intlistshow() { inti,sumfile,sumdir,fl[100],dr[100];//fl为文件的号数,dr为目录的号数 sumfile=sumdir=0; structDIR*dir; dir=(structDIR*)(file+currentdir*BLOCK_SIZE); for(i=0;i { if(dir->list[i].length==0&&(strcmp(dir->list[i].fname,"")! =0)&&(dir->list[i].fnum! =0))//为目录的 { dr[sumdir]=i; sumdir++; } if(dir->list[i].length! =0&&strcmp(dir->list[i].fname,"")! =0)//为目录的 { fl[sumfile]=i; sumfile++; } } for(i=0;i printf("%s文件夹\n",dir->list[dr[i]].fname); for(i=0;i printf("%s%s文件\n",dir->list[fl[i]].fname,dir->list[fl[i]].exname); printf("\n"); printf("\n在该目录下共有%d个文件,%d个文件夹\n\n",sumfile,sumdir-2); return0; } /* *删除子目录 */ intrmdir(char*str) { inti; intflag=0; //FAT号 intblocknum;//目录块 structfatid*FAT; structDIR*dir; structDIR*flagdir;//标记目录块 charc='a';//做用户交互 intm=2;//从第三个子目录项开始搜索要删除的目录项情况 FAT=(structfatid*)(file+BLOCK_SIZE); dir=(structDIR*)(file+currentdir*BLOCK_SIZE);//当前目录指针 MAP=(structmap*)(file+(FATNUM+1)*BLOCK_SIZE); for(i=2;i { if(strcmp(dir->list[i].fname,str)==0)//找到要删除的子目录 { break; } } if(i>LIST_SIZE) { printf("该文件夹下不存在%s",str); return0; } while (1) { printf("是否确认? (Y/N)"); cin>>c; if((c=='y'||c=='Y')||(c=='n'||c=='N')) break; } if(c=='n'||c=='N') return0; blocknum=dir->list[i].fnum; flagdir=(structDIR*)(file+blocknum*BLOCK_SIZE); while(m! =LIST_SIZE) { if(strcmp(flagdir->list[m].fname,"")! =0) { printf("该目录下有子文件或者子目录,不能删除该目录"); } m++; } strcpy(dir->list[i].fname,"");//父目录DIR strcpy(dir->list[i].exname,""); dir->list[i].fnum=0; strcpy(flagdir->list[0].fname,"");//要删除目录的DIR strcpy(flagdir->list[0].exname,""); flagdir->list[0].fnum=0; strcpy(flagdir->list[1].fname,""); strcpy(flagdir->list[1].exname,""); flagdir->list[0].fnum=0; MAP->maplist[blocknum]=0; FAT->id[blocknum]=0; FAT->id[0]=FAT->id[0]+1; return0; } /* *更改当前目录 */ intchangedir(char*str) { inti; intblocknum;//当前目录位置 //temp的目录位置 structDIR*flagdir,*dir; stringstrflag;//为了改当前显示的代码 dir=(structDIR*)(file+currentdir*BLOCK_SIZE); if(strcmp("..",str)==0)//判断是不是上层目录 { blocknum=currentdir; if(dir->list[0].fnum==dir->list[1].fnum)//根目录的特征 { return1; } currentdir=dir->list[1].fnum;//改变当前目录指针 flagdir=(structDIR*)(file+currentdir*BLOCK_SIZE);//去上层的目录地址 for(intj=0;j { if(flagdir->list[j].fnum==blocknum) { strflag=flagdir->list[j].fname; break; } } CURRENT=CURRENT.substr(0,(CURRENT.length()-strflag.length())-1); return1; } for(i=2;i { if(strcmp(dir->list[i].fname,str)==0&&strcmp(dir->list[i].exname,"dir")==0) { currentdir=dir->list[i].fnum; break; } } if(i>LIST_SIZE) { printf("找不到指定的目录%s\n",str); return0; } CURRENT=CURRENT+str+"\\"; return1; } /* *创建文件 */ intcreate(char*str,intlength) { //getfilename inti,j,l,t,k; //FAT的首块号 int
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统