操作系统实验报告实验四.docx

上传人:b****7 文档编号:10305518 上传时间:2023-02-10 格式:DOCX 页数:60 大小:280.79KB
下载 相关 举报
操作系统实验报告实验四.docx_第1页
第1页 / 共60页
操作系统实验报告实验四.docx_第2页
第2页 / 共60页
操作系统实验报告实验四.docx_第3页
第3页 / 共60页
操作系统实验报告实验四.docx_第4页
第4页 / 共60页
操作系统实验报告实验四.docx_第5页
第5页 / 共60页
点击查看更多>>
下载资源
资源描述

操作系统实验报告实验四.docx

《操作系统实验报告实验四.docx》由会员分享,可在线阅读,更多相关《操作系统实验报告实验四.docx(60页珍藏版)》请在冰豆网上搜索。

操作系统实验报告实验四.docx

操作系统实验报告实验四

北京航空航天大学计算机学院

《操作系统》实验报告

实验四[Linux]文件系统

 

实验小组

学号

姓名

小组组长

36060302

温莎莎

小组成员

36060304

徐艺境

小组成员

36060307

李毅

小组成员

36060323

阎春龙

 

2009年6月15日

1.

需求说明

1.1.基本需求

准备一张FAT16格式的U盘(可以将U盘在Windows下直接格式化为FAT16格式),在Linux下编写一个文件系统管理程序,对U盘上的文件进行管理。

具体要求如下:

(1)设计并实现一个目录列表函数(类似于Linux中的Shell命令ls)。

该函数只需要包含基本命令即可,不必支持许多选项。

函数格式为:

intud_ls();

(2)设计并实现一个改变目录函数,即把当前目录切换到上一层目录或当前目录的子目录中(无需处理路径名),函数格式为:

intud_cd(char*directory);

本函数假设U盘上已存在子目录。

需要在文件系统中使用一个静态变量来代表当前目录。

本函数要对当前目录变量进行操作,并且可以返回上一级目录,需要在文件系统中使用一个静态变量来代表当前目录的父目录。

(3)设计并实现一个删除文件函数,该函数使用要删除的文件名(在当前目录中)作为参数,函数格式为:

intud_df(char*name);

该函数需要查找文件,遍历FAT中的链接,设置FAT中的每个簇项并将其标志为未使用,更新目录项。

在删除的情况中,要注意文件的隐藏、只读和系统属性。

任何具有这些设置的文件都不能删除。

(4)设计并实现一个创建文件函数,该函数使用要创建的文件名和文件大小为参数,函数格式为:

intud_cf(char*filename,intsize);

该函数需要遍历FAT表中的链接,找出FAT表中的能存放下文件大小的空簇,并更新目录项,可以用ud_ls()函数查询到创建的文件。

1.2.进阶需求

(1)增加删除目录的功能。

设计并实现一个删除目录函数,通常需要先判断目录是否为空目录,若目录不为空,则需给出提示,并删除其包含的所有子目录和文件;若是空目录则可直接删除。

函数格式为:

intud_dd(char*directory);

(2)增加对绝对路径和多级目录的支持。

这里需要对输入的目录路径字符串进行解析,然后逐级查找目录。

(3)对ud_cf()函数进行改进,使其可以向文件中写入实际内容,并根据写入的内容计算文件实际大小。

(4)对ud_ls()函数进行完善,增加对全部非根目录信息的读取(本实验中只读取了一个扇区的非根目录信息)。

2.设计说明

2.1.结构设计

图2.1程序结构设计图

2.2.功能设计

2.2.1.重要的数据结构设计

结构名称

结构标识名称

字段信息

字段说明

结构功能描述

启动记录

BootDescriptor

unsignedcharOem_name[9]

原始设备制造商名称

以结构体形式存储FAT表中关于文件系统启动记录的信息

intBytesPerSector

每扇区的字节数

intSectorsPerCluster

每簇的扇区数

intReservedSectors

保留的扇区

intFATs

FAT表个数

intRootDirEntries

根目录个数

intLogicSectors

扇区个数

intMediaType

介质类型

intSectorsPerFAT

每个FAT表的扇区数

intSectorsPerTrack

每个磁道的扇区数

intHeads

磁头个数

intHiddenSectors

隐藏扇区数

根目录项

Entry

unsignedcharshort_name[12]

短文件名

存储当前目录下的目录项信息

unsignedcharlong_name[27]

长文件名

unsignedshortyear,month,day

目录项创建日期

unsignedshorthour,min,sec

目录项创建时间

unsignedshortFirstCluster

目录项首簇

unsignedintsize

目录项大小

unsignedcharreadonly:

1

读写属性

unsignedcharhidden:

1

隐藏属性

unsignedcharsystem:

1

系统属性

unsignedcharvlabel:

1

卷标属性

unsignedcharsubdir:

1

子目录属性

unsignedchararchive:

1

归档属性

表2.1结构类型设计说明表

2.2.2.主要函数或接口设计

2.2.2.1.接口清单

/***********************************************************/

/*全局变量定义*/

intfd;//文件描述符

BootDescriptorbdptor;//启动记录

Entry*curdir=NULL;//当前目录

intdirno=0;//代表目录的层数

Entry*fatherdir[10];//父级目录

unsignedcharfatbuf[512*250];//存储FAT表信息

/***********************************************************/

/*全局函数声明*/

intud_ls(int);//显示当前目录的内容

intud_cd(char*);//改变目录到父目录或子目录

intud_cf(char*,int);//在当前目录下创建文件

intud_md(char*);//在当前目录下创建目录

intud_df(char*);//删除当前目录下的文件

intud_dd(char*);//删除当前目录下的目录项

intud_rf(char*);//读取当前目录下的文件内容

voidfindDate(unsignedshort*,unsignedshort*,unsignedshort*,unsignedchar[]);

voidfindTime(unsignedshort*,unsignedshort*,unsignedshort*,unsignedchar[]);

intreadFat();//读fat表的信息

intwriteFat();//将改变的fat表值写回fat表

voidscanBootSector();//浏览启动扇区

voidscanRootEntry();//浏览根目录

intscanEntry(char*,Entry*,int);//浏览当前目录

intgetEntry(Entry*);//从根目录或文件簇中得到文件表项

voidformatFileName(unsignedchar*);//文件名格式化

unsignedshortgetFatCluster(unsignedshort);//在fat表中获得下一簇的位置

voidclearFatCluster(unsignedshort);//清除fat表中的簇信息

2.2.2.2.函数功能说明

函数名称

返回类型

参数

功能描述

ud_ls

int

int

显示当前目录的内容

ud_cd

int

char*

改娈当前目录到父目录或子目录

ud_cf

int

char*

在当前目录下创建文件

int

ud_md

int

char*

在当前目录下创建子目录

ud_df

int

char*

删除当前目录下的文件

ud_dd

int

char*

删除当前目录下的子目录

ud_rf

int

char*

读取当前目录下的文件内容

readFat

int

读取FAT表信息

writeFat

int

将改变的FAT表值写回FAT表

scanBootSector

void

浏览启动扇区

scanEntry

int

char*

浏览当前目录项

Entry*

int

getEntry

int

Entry*

获取目录项在FAT表中的位置

getFatCluster

unsignedshort

unsignedshort

获取下一簇在FAT表中的位置

clearFatCluster

void

unsignedshort

清除FAT表中的簇信息

formatFileName

void

unsignedchar*

文件名格式化

findDate

void

unsignedshort*

读取日期

unsignedshort*

unsignedshort*

unsignedchar[]

findTime

void

unsignedshort*

读取时间

unsignedshort*

unsignedshort*

unsignedchar[]

表2.2函数功能说明表

2.2.2.3.函数调用关系

图2.2函数调用关系图

2.2.2.4.重要功能具体说明

2.2.2.4.1.创建目录功能的实现

本程序实现了在当前目录下创建子目录的功能。

函数ud_md(),接受参数为要在当前目录下创建的子目录的名称。

创建成功则返回值为1,失败则返回值为-1,若当前目录下存在同名子目录,则不创建目录并打印提示信息告之用户。

该函数先遍历FAT表,找到一个空簇作为提供给将要创建的目录结构中的首簇指向。

之后获取新建的子目录在根目录区的存储地址,并将各字节信息存入。

2.2.2.4.2.删除目录功能的实现

实现了函数ud_dd(),接受参数为要删除当前目录下的子目录名称。

删除成功则返回值为1,失败则返回值为-1。

该函数先遍历当前目录,获得要删除子目录的目录项结构信息。

之后,读取目录项结构中的首簇地址字段,查看其指向地址的簇是否为文件结束簇,即判断该目录是否为空。

若为空,则直接调用clearFatCluster()函数清除FAT表中该目录的记录;若不为空,则向用户发出提醒并询问用户是否删除。

在删除不为空的目录时,应遍历其下的文件及子目录,递归调用相应的目录项删除函数将它们存储在FAT表中的信息清除掉,然后再删除最顶层的目标目录。

如是,则完成了删除一个指定目录的操作。

2.2.2.4.3.对绝对路径和多级目录的支持

在系统接收cd命令后,先对其后输入的转移目录路径字符串进行解析判断其属于绝对路径形式、多级目录形式还是单级目录形式。

若路径字符串以“/media/disk/”开头,则显然匹配为绝对路径。

取其后的子字符串,先跳转到U盘文件系统下的根目录,之后按多级目录形式对取出的子字符串进行处理。

若路径字符串中含多个目录分隔号“/”,则显然匹配为多级目录。

从头到尾遍历该字符串,将每两个分隔符间的目录作为子字符串取出,按单级目录形式传给cd函数处理。

这样每处理完一个子串,则当前目录路转到该目录下,直到字符串遍历完成。

其余情况均作为单级目录处理,若字符串为“.”,则保持当前目录不变;若字符串为“..”,则跳转到当前目录所在的父一级目录,同时修改存储父级目录的记录表指向的目录地址;若字符串为目录名称,将要跳转的子目录名字符串作为参数传递给cd函数处理,将当前目录修改为其下的这一子目录,并将改变前的目录存入存储父级目录的记录表中。

2.2.2.4.4.创建文件函数的改进

在创建文件函数ud_cf()中,加入了对用户写入文件内容的支持。

在执行用户输入的cf命令时,首先获取用户输入的文件内容,通过调用ud_cf()函数创建文件时,在FAT表中查找空白簇,将文件内容存入数据区相对应于找到并建立好的FAT表链接。

关键代码实现如下:

printf("enterthefile'sdata:

\n");

scanf("%s",data);

size=strlen(data);

clustersize=size/CLUSTER_SIZE;

if(size%CLUSTER_SIZE!

=0)

clustersize++;

/*查询fat表,找到空白簇,保存在clusterno[]中*/

for(cluster=2;cluster<1000;cluster++)

{

index=cluster*2;

if(fatbuf[index]==0x00&&fatbuf[index+1]==0x00)

{

clusterno[i]=cluster;

i++;

if(i==clustersize)

break;

}

}

/*在fat表中写入下一簇信息*/

for(i=0;i

{

index=clusterno[i]*2;

fatbuf[index]=(clusterno[i+1]&0x00ff);

fatbuf[index+1]=((clusterno[i+1]&0xff00)>>8);

if(lseek(fd,(clusterno[i]-2)*CLUSTER_SIZE+DATA_OFFSET,SEEK_SET)<0)

perror("lseekfiledatafailed");

if(write(fd,data+i*CLUSTER_SIZE,CLUSTER_SIZE)<0)

perror("writefailed");

}

/*最后一簇写入xffff*/

index=clusterno[i]*2;

fatbuf[index]=0xff;

fatbuf[index+1]=0xff;

if(lseek(fd,(clusterno[i]-2)*CLUSTER_SIZE+DATA_OFFSET,SEEK_SET)<0)

perror("lseekfiledatafailed");

if(write(fd,data+i*CLUSTER_SIZE,size-i*CLUSTER_SIZE)<0)

perror("writefailed");

文件大小是由用户输入文本数据后根据其大小求得。

在FAT表进行写入下一簇信息的同时,在数据区相应簇中写入文件数据。

这样FAT表在建立对数据区数据存储的索引时,也完成了文件数据的存入。

2.2.2.4.5.读取文件函数的实现

实现了函数ud_rf()用于读取磁盘中的文件内容。

在获取了所要读取的文件的目录项信息后,根据首簇地址在FAT表中顺序查找数据区该文件内容的存储地址,读出并打印。

关键代码实现如下:

seed=pentry->FirstCluster;

size=pentry->size;

page=size/CLUSTER_SIZE;

buf=(unsignedchar*)malloc(sizeof(unsignedchar)*size);

for(i=0;i

{

if((ret=lseek(fd,(seed-2)*CLUSTER_SIZE+DATA_OFFSET,SEEK_SET))<0)

perror("lseekcluster_addrfailed");

read(fd,buf+i*CLUSTER_SIZE,CLUSTER_SIZE);

seed=getFatCluster(seed);

}

if((ret=lseek(fd,(seed-2)*CLUSTER_SIZE+DATA_OFFSET,SEEK_SET))<0)

perror("lseekcluster_addrfailed");

read(fd,buf+i*CLUSTER_SIZE,size-i*CLUSTER_SIZE);

for(i=0;i

printf("%c",buf[i]);

printf("\n");

按目录表项中文件大小字段值先求得文件数据所占数据区的簇数后,按FAT表中索引依次从所在的各簇中读取数据,转存打印。

2.2.2.4.6.目录列表函数的完善

检查用户输入的ls命令后所带参数项,若为-all,则传递参数1给函数ud_ls(),打印所有非根目录的信息;若为-cur,则传递参数0给函数ud_ls(),打印当前目录的信息(这与dir命令功能相同)。

非根目录列表:

在函数ud_ls()中通过不断调用函数ud_cd()来改变当前目录,并打印即时当前目录的信息,即实现了所有非根目录列表显示的功能。

当前目录列表:

在函数中从当前目录起始地址开始遍历,获取当前目录下的目录项,并打印显示,即实现了当前目录列表显示的功能。

3.测试和使用说明

3.1.使用说明

3.1.1.开发环境

Linux操作系统版本:

Ubuntu9.04

集成开发环境:

eclipse-SDK-3.4.2-linux-gtk

GCC编译器:

gcc-4.3.3

3.1.2.运行环境

Linux操作系统平台

FAT16格式的U盘

3.1.3.安装说明

将程序文件夹中的可执行文件filesystem.out复制到Linux系统的桌面上,插入一张在windows系统下格式化为FAT16格式的U盘,在终端中修改当前路径进入桌面,执行命令./filesystem.out,即可运行文件管理主程序,它读取FAT表中启动记录信息并显示后,打印命令提示符‘>’,等待用户输入文件管理命令并进行相关处理。

3.2.测试说明

3.2.1.测试用例

3.2.1.1.输入描述

插入格式化为FAT16格式的U盘,运行程序的可执行文件。

看到启动记录被正常打印后,用户可根据随之打印出的帮助信息中文件管理相关命令格式,输入相应命令,执行相应的文件管理操作。

附:

文件管理格式命令说明

命令名称

命令格式

描述说明

目录列表命令

ls–a或ls-all

列表显示所有非根目录项。

目录列表命令

ls–c或ls-cur

列表显示当前目录下所有目录项

改变目录命令

cd

将当前目录改变为参数字符串所代表的目录路径。

创建文件命令

cf

在当前目录下新建一个文件,命令后面第一个参数为文件名,第二个参数为预设定的大小。

执行该命令后,用户可随即输入文件内容并保存。

创建目录命令

md

在当前目录下新建一个目录,参数代表目录名称。

删除文件命令

df

删除当前目录下的文件,参数字符串代表要删除的文件名称。

删除目录命令

dd

删除当前目录下的目录,参数字符串代表要删除的目录名称。

若该目录为空则直接删除,若不为空,则询问用户,得到删除的确认后,该其下子目录项全部删除。

读取文件命令

rf

打开当前目录下的一个文件,并将文件中的内容打印出来,参数字符串代表要查看内数的文件名称。

表3.1文件管理格式命令说明表

3.2.1.2.输出描述

程序启动后,首先打印了磁盘的启动记录。

其后,依照用户输入的文件管理命令,执行相应操作,打印与其相符的信息,确保文件管理被正确执行。

3.2.2.运行结果

图3.1磁盘启动记录运行截图

图3.2目录列表命令记录运行截图

图3.3切换目录命令运行截图

图3.4创建文件命令运行截图

4.其他说明

4.1.组内成员任务分工说明

成员姓名

任务分工

任务所占比例

完成情况

温莎莎

ud_ls函数的实现

30%

出色完成

功能实现

ud_df函数的实现

相关支持

徐艺境

ud_cd函数的实现

30%

出色完成

功能实现

ud_md函数的实现

相关支持

李毅

程序数据结构和接口标准的建立

30%

出色完成

功能实现

ud_cf、ud_dd、ud_rf函数的实现

程序的结构组织和运行体系的完善

文档编写

阎春龙

10%

4.2.完成情况说明

实现了所有要求的基本功能和建议的扩展功能。

5.程序清单

5.1.file_global

/*

*file_global.h

*

*Createdon:

2009-5-28

*Author:

liyi

*/

#ifndefFILE_GLOBAL_H_

#defineFILE_GLOBAL_H_

/***********************************************************/

/*全局常量定义*/

#defineDEVNAME"/dev/sdc"//要打开的设备文件名,表示当前使用的U盘

#defineDIR_ENTRY_SIZE32//目录项大小

#defineSECTOR_SIZE512//每个扇区大小

#defineCLUSTER_SIZE512*4//每个簇大小

#defineFAT_SIZE250*512//每个FAT表大小

#defineFAT_ONE_OFFSET512//第一个FAT表起始地址

#defineFAT_TWO_OFFSET512+250*512//第二个FAT表起始地址

#defineROOTDIR_OFFSET512+250*512+250*512+512//根目录区起始地址

#defineDATA_OFFSET512+250*512+250*512+512*32//数据区起始地址

/**属性位掩码**/

#defineATTR_READONLY0x01

#defineATTR_HIDDEN0x02

#defineATTR_SYSTEM0x04

#defineATTR_VLABEL0x08

#defineATTR_SUBDIR0x10

#defineATTR_ARCHIVE0x20

/**时间掩码5:

**/

#defineMASK_HOUR0xf800

#defineMASK_MIN0x07e0

#defineMASK_SEC0x001f

/**日期掩码**/

#defineMASK_YEAR0xfe00

#defineMASK_MONTH0x01e0

#defineMASK

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 军事

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1