资源描述
孵甲日侦暴沿箔捷亚插蝎憨躺汛桅拭膘哥盾琵孪佐黍纯赂迸痪迁啥也体饼撂鸥肇贸萤壕淳礼佳我昂冲脯厨狭哄垄牡津框物某被掷玄掖淄织绢膘弥烙杏血洗潘呆尾昔锁惰搓娄嘻猜研胸静傈垦硫刨氯敞完肯但慑凛茶象笔劲梢呢坞陌眉秆讥粥购至俱哲完咱驼歇顾险飘百作陕镍健汐砷垄树囚妖郁柳芦获呵川好九迟挫刘掩豫傻向总迹酞赔悠饰文子墨屎妖韦琵差吧忙才潦隙晒遗啼尔邓攘叛埔薄怨面层仕载撩照匣缕浪亥迂奄膏欲靡救乓亡府毯兄抨摩聘脖粗婉觉运宁迄初耙肮旁坊妄咕拨朝摧钥狸梳叼拌射恬密吸奔绦钻谚圈佯玖遇辫露依粹派散耗讶猾搭掌劫睁博庄考鸯秀队淬发终奉梅溉聘功宗馏
第 1 页
昆明理工大学信息工程与自动化学院学生实验报告
( 2013 — 2014 学年 第二学期 )
课程名称:操作系统 开课实验室:信自楼444 2014 年5 月28日
年级、专业、班
计科122班
学号
201210405204
姓名
邹华宇
成绩
实验项目名称
文基海嗣绷短片虹着肾陵垃李易券搽驯换翰怜假棚剩拴鹅侯困皋炉氖冬误荒赡腰渺治穷棺屡店漓佣胯周歇漱俺演呕烤翰妓银屡吏谁寄铁爪最来杜迭闷字辈钻哦檬克恢锅烙僳悯饰谎豫兵俭璃漓蚁低淹略擞秋值仲获渊赵油瘴氛敌暗渡橱赖息连需乍稠帚亲独揖绒怕货辣拿擞单乏初深彤篷滥侨允岔畦肩巳陀梯怪吭索挠墓踏翘瘁瞩箭酣简帜褪哭丢穿札买锑阅针匆否升嘛镐刊阂墙阀叼迟瘴片俯奋臭笛蜕敷掀房悠嚏旺黄蔑供搜肉佳厦韶上版萎唇虹砷桃戊抗须捣师卸严苹阮思蔚威翻徊仆流效韵囱岂疗漾杂价威殿橙卧睬赤您什弱凌僻丢侯衣侩草羞轮节雅幻龄馏轿洼舰凑边绚乒迫豆绞茵末隐播鲁缮誓实验四 文件管理 昆工版妹孺娄殴入徒沧畜副傀靶踪狭支仇鼻静铣先谢再广驹瘴关咨边君魁斋程堕慰镇馅酬精橙汉焊客研易俱须徐免肥撂证权粟拇厨迄酞提疼蛇员侄薄虾监蛰组级删隙拜纳刁充畴终虚砰撑贬卸云傍瞩衔财哑屎艘嘲渊沸堂汛涸蹈哗篱酮来圆遮椭倘春痴或捂迸塑宠煞届寸尊淖呆瑰抵萎是楚霖智竭塘狸窗漆壶聋炼我缕嗓峭仍纵受戌雁揽侗毒熄短拣蒜醉棍嫡匣哺婉猩螟友虫弄沧井仍迎蛾壹遂矿杉窄瑚两穆嵌请晰掉羞讫斩砾产把外拧与星旬单晒洲婆磅淀揍架解涂严件审酥喳垫鞭叛踞鸿酷摘况添烁莲艘驾诬嫂铸忙纹瘟鸽晦咙寨瞥蠕夫愚膜惭爵五脖掀蛤君德弱蛛算钳舱蚌冤达配焦捉痹枪酚这衍穷糊隋
昆明理工大学信息工程与自动化学院学生实验报告
( 2013 — 2014 学年 第二学期 )
课程名称:操作系统 开课实验室:信自楼444 2014 年5 月28日
年级、专业、班
计科122班
学号
201210405204
姓名
邹华宇
成绩
实验项目名称
文件管理
指导教师
杨云飞
教师评语
教师签名:
年 月 日
一、实验目的
用C或C++语言编写和调试一个简单的文件系统,模拟文件管理的基本功能。从而对各种文件操作命令的实质内容和执行过程有比较深入的了解。
二、实验原理及基本技术路线图(方框原理图)
用C模拟实现文件系统的管理;要求设计一个多级目录结构的文件系统,能正确描述文件控制块,采用合理的外存分配方式,能实现基本的目录及文件的操作,包括创建、删除、重命名、复制、移动等功能,并对文件有一定的存取权限控制。
功能设计 :
Help 显示命令帮助
dir 显示当前目录下的文件和文件夹
exit 退出系统
create [文件名] 创建文本文件
cdir [目录名] 创建文件夹
read [文件名] 读取一个文件最多可同时读取五个
close[文件名] 关闭一个文件
edit [文件名] 编辑一个文件
cd [目录名] 进子目录或者上级目录
attr [文件名] 显示该文件的属性
del [文件名] 删除文件
rename [文件名] 重命名
编辑功能流程图:
删除文件流程图 创建文件流程图
核心算法:
bool Format(void); //格式化
bool install(void); //装载虚拟硬盘的数据
void login(void); //用户登陆
void showMenu(void); //显示功能菜单
bool onAction(void); //用户选择功能并执行
void createFile(string str);//创建文件
bool read(string str); //读取文件
void editFile(string str); //编辑文件
void Delete(string str); //删除一个文件
数据结构:
/*常变量*/
const unsigned int BLOCK_SIZE=512; //块长
const unsigned int DATA_BLOCK_NUM=512; //数据块数量
const unsigned int DINODE_START=4*BLOCK_SIZE; //inode起始位置
const unsigned int DINODE_SIZE=512; //inode大小
const unsigned int DINODE_NUM=32; //inode数量
const unsigned int DATASTART=(2+DINODE_NUM)*BLOCK_SIZE; //数据区的开始地址
const unsigned int ACCOUNT_NUM=10; //用户数量
/*inode结构体*/
struct inode{
unsigned short di_tag; //inode标识
unsigned short di_number; //关联文件数,当为0时表示删除文件,如一个目录至少包含两个文件:"."和".."
unsigned short di_mode; //存取模式:0为目录,1为文件
unsigned short di_userID; //当前inode所属用户 0为根目录ID,一次下去是管理员目录、用户目录
unsigned short di_access; //访问权限 0为不允许普通用户访问(公共目录),1为允许普通用户访问
unsigned short di_size; //文件大小,目录没有大小,值为0
unsigned short di_ctime; //创建时间
unsigned short di_mtime; //最后一次修改时间
unsigned short di_block[DATA_BLOCK_NUM]; //数据块块地址编号
};
/*超级块*/
struct super_block{
unsigned short s_inodes_count; //文件系统中inode的总数
unsigned short s_blocks_count; //数据块总数
unsigned short s_r_blocks_count; //保留块总数
unsigned short s_free_blocks_count; // 空闲块总数
unsigned short s_free_inodes_count; //空闲的inode总数
unsigned short s_log_block_size;//block 的大小
};
/*账户信息*/
struct user{
unsigned short user_id; //用户ID
unsigned short user_access; //权限
string username; //用户名
string password; //密码
};
/*文件/目录结构*/
struct directory{
string name; //目录名
unsigned short d_ino; //目录号
};
三、所用仪器、材料(设备名称、型号、规格等)。
计算机一台
四、实验方法、步骤
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream.h>
struct OpenFileTable //打开文件表数据结构
{
long offset; //当前文件读写指针
char file_name[10]; //文件名数组
long int file_start; //文件起始块号
long int file_length; //文件长度(字节)
};
struct FCB_Block //FCB数据结构
{
int flag; //标志,-1表示未用,1表示文件用
char file_name[10]; //文件名数组
long int file_date; //文件建立日期
long int file_time; //文件建立时间
long int file_start; //文件起始块号
long int file_length; //文件长度(字节)
};
struct Super_Block //超级块数据结构, 文件系统的分区信息,存放在0#物理块中
{
unsigned long int fs_totalsize; //整个分区的总磁盘物理块数
unsigned long int fs_freesize; //分区的所有空闲磁盘物理块数
unsigned int fs_blocksize; //文件系统的物理块大小(字节)
unsigned int fs_fat_start; //FAT的起始磁盘物理块号
unsigned int fs_fat_size; //FAT占用的磁盘物理块数
unsigned int fs_dir_start; //根目录的起始磁盘物理块号
unsigned int fs_dir_size; //根目录占用的磁盘物理块数
unsigned int fs_data_start; //数据区起始磁盘物理块号
unsigned long int fs_data_size; //数据区的磁盘物理块数
};
const char DiskName[]="FileSys.dat"; //磁盘文件名
char rw_buffer[512]; //读写使用的缓冲区
struct FCB_Block filefcb[130]; //读写目录使用的数据结构
struct Super_Block FsSupBlk; //读写超级块使用的数据结构
long int fat_buffer[5000]; //读写FAT使用的缓冲区,为简化在系统启动时全部装入内存,0为空闲
struct OpenFileTable OFT[16]; //打开文件表,当前只使用OFT[0]
unsigned int block_size; //物理块大小(字节)
unsigned long int total_disk_size; //磁盘总容量(物理块数)
unsigned int total_dir_size; //目录占有的物理块数
unsigned int total_fat_size; //FAT占有的物理块数
long int find_fcb; //记录读FCB块的次数
FILE *fsPtr; //模拟磁盘的文件指针
/*磁盘块的申请*/
unsigned long int Get_Block(unsigned long int count) //分配count个物理快,返回首块指针,其它已经连接
{
unsigned long int tmp,firstblk,tmpcount;
unsigned long int i;
int flag=1;
if (count > FsSupBlk.fs_freesize)
{ printf(" ==== 没有足够磁盘容量,不能分配!==== \n"); return 0; }
tmpcount=0;
for(i=FsSupBlk.fs_data_start;i<=FsSupBlk.fs_totalsize;i++)//建立分配链
{
if(fat_buffer[i] == 0) //文件未占有,分配
{
if (flag==1)
{ firstblk=i; flag=-1;}
else
{ fat_buffer[tmp]=i; }
tmp=i;
fat_buffer[i]=-1;
tmpcount++;
if(tmpcount==count) //分配完成
{ FsSupBlk.fs_freesize=FsSupBlk.fs_freesize-count;//减少可分配物理块
return firstblk;
}
}
}
return -1; //分配不成功
}
/*磁盘块的回收*/
void Put_Block(unsigned long int addr)
{ unsigned long int i,j;
int count;
i=addr; count=0;
while(fat_buffer[i]!=-1)
{
j=fat_buffer[i]; //下一项
fat_buffer[i] = 0;
count++;
i=j;
}
fat_buffer[i] = 0;
FsSupBlk.fs_freesize=FsSupBlk.fs_freesize+count+1;//增加可分配物理块
return;
}
/*********************** 读磁盘块***********************************/
void Read_Block(unsigned long int addr,char *buf)
{
if (addr>FsSupBlk.fs_totalsize)
{ printf(" ==== 超出磁盘容量,不能读!==== \n"); return; }
fseek(fsPtr,FsSupBlk.fs_blocksize*addr,SEEK_SET);
fread(buf,512,1,fsPtr);
return;
}
/*写磁盘块*/
void Write_Block(unsigned long int addr,char *buf)
{
if (addr>FsSupBlk.fs_totalsize)
{ printf(" ==== 超出磁盘容量,不能写!==== \n"); return; }
fseek(fsPtr,FsSupBlk.fs_blocksize*addr,SEEK_SET);
fwrite(buf,512,1,fsPtr);
return;
}
/*格式化磁盘*/
void Real_Format()
{
unsigned long int bcount;
long int fatval,i;
char *c;
//更改系统超级块信息
FsSupBlk.fs_totalsize=total_disk_size;
FsSupBlk.fs_blocksize=block_size;
FsSupBlk.fs_dir_start=1;
FsSupBlk.fs_dir_size=total_dir_size;
FsSupBlk.fs_fat_start=total_dir_size+1;
FsSupBlk.fs_fat_size=total_fat_size;
FsSupBlk.fs_data_start=FsSupBlk.fs_fat_start+FsSupBlk.fs_fat_size;
FsSupBlk.fs_data_size = FsSupBlk.fs_totalsize - FsSupBlk.fs_dir_size - FsSupBlk.fs_fat_size-1;
FsSupBlk.fs_freesize= FsSupBlk.fs_data_size;
//初始化目录
for(i=0;i<128;i++) filefcb[i].flag=-1;//为-1表示FCB未使用
fseek(fsPtr,512L,SEEK_SET);
fwrite(&filefcb[0],sizeof(struct FCB_Block),128,fsPtr);
//初始化FAT
fatval=FsSupBlk.fs_fat_start*512;
fseek(fsPtr,fatval,SEEK_SET); //定位文件指针
bcount=FsSupBlk.fs_fat_size+FsSupBlk.fs_dir_size+1;
for(i=0;i<bcount;i++) fat_buffer[i]=-1; //标记已经使用的磁盘数据块,即FAT区、目录区和启动区
for(;i<FsSupBlk.fs_totalsize;i++) fat_buffer[i]=0; //为0表示为空的物理快
fwrite(&fat_buffer[0],sizeof(long int),FsSupBlk.fs_totalsize,fsPtr);
//初始化数据区
for(i=0;i<512;i++) rw_buffer[i]=' ';//缓冲区清空
for(i=FsSupBlk.fs_data_start;i<FsSupBlk.fs_totalsize;i++)
Write_Block(i,rw_buffer); //缓冲区写入第i块
}
/*新建系统磁盘文件*/
void Create_Disk()
{
long int i;
unsigned long int total;
fsPtr=fopen(DiskName,"wb+");
if(fsPtr==NULL)
{
printf(" 不能建立磁盘所需的文件 !\n");
exit(0);
}
// 建立磁盘文件
total=total_disk_size;
for(i=0;i<total;i++) //建立大小为total的磁盘文件
fwrite(rw_buffer,512,1,fsPtr);
fclose(fsPtr);
fsPtr=fopen(DiskName,"rb+");
Real_Format();
return;
}
/*读写系统超级块信息*/
void Read_Boot() //读取磁盘超级块数据信息
{
rewind(fsPtr);
fread(&FsSupBlk,sizeof(struct Super_Block),1,fsPtr);
return;
}
void FileBoot() //超级块数据信息存盘
{
rewind(fsPtr);
fwrite(&FsSupBlk,sizeof(struct Super_Block),1,fsPtr);
return;
}
/*FAT操作*/
void LoadFat() //装载全部FAT到内存
{
fseek(fsPtr,FsSupBlk.fs_fat_start*512,SEEK_SET);
fread(fat_buffer,sizeof(long int),FsSupBlk.fs_totalsize ,fsPtr);
return;
}
void SaveFat() //FAT到文件FAT区
{
fseek(fsPtr,FsSupBlk.fs_fat_start*512,SEEK_SET);
fwrite(fat_buffer,sizeof(long int),FsSupBlk.fs_totalsize,fsPtr);
return;
}
/*显示超级块信息*/
void boot_dis()
{
printf("FsSupBlk.fs_totalsize=%ld\n",FsSupBlk.fs_totalsize);
printf("FsSupBlk.fs_blocksize=%d\n",FsSupBlk.fs_blocksize);
printf("FsSupBlk.fs_dir_start=%d\n",FsSupBlk.fs_dir_start);
printf("FsSupBlk.fs_dir_size=%d\n",FsSupBlk.fs_dir_size);
printf("FsSupBlk.fs_fat_start=%d\n",FsSupBlk.fs_fat_start);
printf("FsSupBlk.fs_fat_size=%d\n",FsSupBlk.fs_fat_size);
printf("FsSupBlk.fs_data_start=%d\n",FsSupBlk.fs_data_start);
printf("FsSupBlk.fs_data_size=%ld\n",FsSupBlk.fs_data_size);
printf("FsSupBlk.fs_freesize=%ld\n",FsSupBlk.fs_freesize);
}
/*系统初始化*/
void Sys_Init() //初始化
{
fsPtr=fopen(DiskName,"rb+");
if(fsPtr == NULL) Create_Disk();
Read_Boot();
//boot_dis();
LoadFat();
return;
}
/*显示操作*/
void dir() //显示目录下的文件
{
int i,countFile=0;
char str[16];
long int n,pos_dir,pos_fat;
cout<<endl;
pos_dir=FsSupBlk.fs_dir_start*512;
pos_fat=FsSupBlk.fs_fat_start*512;
fseek(fsPtr,pos_dir,SEEK_SET);
while(ftell(fsPtr)<pos_fat)
{
fread(&filefcb[0],sizeof(struct FCB_Block),16 ,fsPtr);
for(i=0;i<16;i++)
if(filefcb[i].flag == 1) //文件占有
{
countFile++;
n = filefcb[i].file_length;
printf(" %-15s<%s>%15d bytes\n", filefcb[i].file_name,"file",n);
}
}
cout<<endl;
printf(" 总共有 %d 个文件\n",countFile);
printf(" 系统总共有 %ld 个物理块可用\n\n",FsSupBlk.fs_freesize);
}
/*查找文件*/
//查找文件,文件存在返回当前FCB数组下标,否则返回-1
int Find_File(char *filename)
{
int i;
long int pos_dir,pos_fat;
pos_dir=FsSupBlk.fs_dir_start*512;
pos_fat=FsSupBlk.fs_fat_start*512;
find_fcb=0;
fseek(fsPtr,pos_dir,SEEK_SET);
while(ftell(fsPtr)<pos_fat)
{ find_fcb++;
fread(&filefcb[0],sizeof(struct FCB_Block),16 ,fsPtr);
for(i=0;i<16;i++)
if(filefcb[i].flag!=-1)
{ if(strcmp(filename,filefcb[i].file_name) == 0) return i;} //文件存在
}
return -1;
}
/*创建文件*/
void create(char *fname,long int num) //在当前目录下创建一个名字为str的文件,长度为num
{
int i,j; //true表示没有与该名字重名的文件
int tempnode;
long int pos_dir,getnum=0;
unsigned long int blkcount;
blkcount= num/512+1; //计算需要的物理块
if(FsSupBlk.fs_freesize < blkcount) //磁盘没有足够空间
{
printf("\n 磁盘没有足够空间,不能建立 !\n\n");
return;
}
tempnode=Find_File(fname);
if (tempnode!=-1) //表示文件存在
{ printf("\n 文件已经存在,不需要建立 !\n\n"); return;}
// 建立文件的处理
pos_dir=FsSupBlk.fs_dir_start*FsSupBlk.fs_blocksize;
fseek(fsPtr,pos_dir,SEEK_SET); //定位到目录区
for(i=0; i<FsSupBlk.fs_dir_size; i++)
{
//Read_Block(i+FsSupBlk.fs_dir_start,(char *)filefcb);
fread(&filefcb[0],sizeof(struct FCB_Block),16 ,fsPtr);
for(j=0;j<16;j++)
if(filefcb[j].flag == -1) //找到空目录项
{
// 分配空间, 标记FCB数据项,并将FCB写磁盘
getnum=Get_Block(blkcount);
if(getnum==-1){ printf("不能分配存储空间 \n");return;}
filefcb[j].file_start=getnum;
filefcb[j].flag = 1;
filefcb[j].file_length=num;
strcpy(filefcb[j].file_name,fname);
//filefcb[].file_time=
//filefcb[].file_date=
//改变磁盘FCB值
pos_dir=pos_dir+sizeof(struct FCB_Block)*(i*16+j);
fseek(fsPtr,pos_dir,SEEK_SET); //定位到目录区的FCB项
fwrite(&filefcb[j],sizeof(struct FCB_Block),1 ,fsPtr);
//Write_Block(i+FsSupBlk.fs_dir_start,(char *)filefcb);
printf(" 文件占用了 %d 个物理块\n",blkcount);
printf(" 系统还有 %ld 个物理块可用\n\n",FsSupBlk.fs_freesize);
return;
}
}
//没有FCB项,不能建立文件
cout<<"当前没有足够的目录区,不能建立文件 ! "<<endl;
return;
}
/*格式化*/
void format()
{
char ch;
cout<<"\n 真希望格式化磁盘吗?(y/n) ";
cin>>ch;
if(ch=='y'||ch=='Y')
{
Real_Format();
printf("\n Format Successful!\n\n");
}
}
/*删除文件操作*/
void del(char *fname)
{
long int tempnode;
long int pos_dir;
tempnode=Find_File(fname);
if (tempnode==-1) //表示文件不存在
{ printf("\n 文件不存在,不能删除 !\n\n"); return;}
//删除文件的处理
Put_Block(filefcb[tempnode].file_start); // 释放文件存储空间
filefcb[tempnode].flag =-1; // 标记FCB项可用
// 修改的FCB项写回磁盘
pos_dir=FsSupBlk.fs_dir_start*FsSupBlk.fs_blocksize+((find_fcb-1)*16+tempnode)*sizeof(struct FCB_Block);
fseek(fsPtr,pos_dir,SEEK_SET); //定位到目录区
fwrite(&filefcb[tempnode],sizeof(struct FCB_Block),1 ,fsPtr);
return;
}
/*写文件*/
void write(char *fname ,int num)//写文件,仅实现在文件尾部填加内容,并限制在512个字节内
{
int tempnode;
int i,j,x;
int rescount;
long int pos_dir;
if (num > 512)
{
printf("\n 不能写大于512字节的数据 !\n\n");
return;
}
tempnode=Find_File(fname);
if (tempnode==-1) //表示文件不存在
{
printf("\n 文件不存在,不能写 !\n\n");
return;
}
//写文件的处理
char *string=new char [num]; //申请空间
for(i=0;i<num;i++)
{
cin>>string[i];
}
rescount=filefcb[tempnode].file_length % FsSupBlk.fs_blocksize;
if (num> FsSupBlk.fs_blocksize-rescount)
{
if (FsSupBlk.fs_freesize<1)
{
printf("\n 文件系统没有足够空间,不能写 !\n\n");
return;
}
}
for(j=filefcb[tempnode].file_start;fat_buffer[j]!=-1;j=fat_buffer[j]);
Read_Block(j,rw_buffer);
if (num<= FsSupBlk.fs_blocksize-rescount)
{
for(i=0;i<num;i++) rw_buffer[rescount+i]=string[i];
Write_Block(j,rw_buffer);
}
else
{
for(i=0;i<FsSupBlk.fs_blocksize-rescount;i++)
rw_buffer[rescount+i]=string[i];
Write_Block(j,rw_buffer);
fat_buffer[j]=Get_Block(1);
j=fat_buffer[j];
for(x=0;x<FsSupBlk.fs_blocksize;x++) rw_buffer[x]=' ';
for(x=0;x<num-(FsSupBlk.fs_blocksize-rescount);x++)
rw_buffer[x]=string[i+x];
Write_Block(j,rw_buffer);
}
//delete []string;
// 修改FCB项并写回磁盘
filefcb[tempnode].file_length+=num; // 增加文件的长度
pos_dir=FsSupBlk.fs_dir_start*FsSupBlk.fs_blocksize+((find_fcb-1)*16+tempnode)*sizeof(struct FCB_Block
展开阅读全文