操作系统大作业ufs文件系统.docx
《操作系统大作业ufs文件系统.docx》由会员分享,可在线阅读,更多相关《操作系统大作业ufs文件系统.docx(15页珍藏版)》请在冰豆网上搜索。
操作系统大作业ufs文件系统
操作系统课程设计
一个用户级文件系统的设计
目录
1、课程设计的主要目的-------------------------------------------3
2、相关的技术背景-----------------------------------------------3
2.1.文件系统简介--------------------------------------------3
2.2.FUSE简介-----------------------------------------------3
2.3.解压FUSE-----------------------------------------------4
2.4.编译并安装FUSE-----------------------------------------5
3、主要思想和技术路线-------------------------------------------5
3.1.数据结构定义--------------------------------------------5
3.2.主要函数定义--------------------------------------------5
3.2.1.u_fs函数-------------------------------------------6
3.2.2.base函数-------------------------------------------8
4、测试结果-----------------------------------------------------9
4.1.创建文件系统-------------------------------------------9
4.2.文件夹测试--------------------------------------------10
4.3.文件测试----------------------------------------------11
4.4.测试格式化功能----------------------------------------12
4.5.卸载文件系统------------------------------------------12
5、源代码的目录结构及存放位置----------------------------------13
6、运行环境----------------------------------------------------13
1课程设计的主要目的
更加深入地理解文件系统的原理和设计,了解在linux平台下的编程,加强学生动手能力,丰富代码经验。
实现两层目录系统,有以下的要求和限制:
1.根目录可以包含子目录和普通文件
2.子目录只能包含普通文件,不能包括其他子目录
3.所有文件都能可读写(改变模式0666),忽略权限
4.许多文件属性如创建和修改时间不需要准确地储存,
5.文件不能被截断
6.目录看成是文件
2.相关的技术背景
2.1文件系统
文件系统是一种用来存储和组织计算机文件、目录及其包含的数据的方法,它使文件、目录以及数据的查找和访问得到简化。
文件系统能提供丰富的扩展能力。
它可以编写成底层文件系统的一个封装程序,从而对其中的数据进行管理,并提供一个增强的、具有丰富特性的文件系统。
2.2FUSE简介
FUSE是linux平台下使用用户空间的文件系统。
我们不需要了解linux内核模块的编程知识,只要利用FUSE提供的文件系统框架,就可以创建自己的功能完备的文件系统。
FUSE主要是由以下的三部分构成:
●内核模块FUSE
●用户空间库libfuse
●mount/umount程序fusermount
在FUSE中创建一个文件系统,先安装一个FUSE内核模块,然后使用FUSE库和API。
用户空间进程在执行操作文件的系统调用的时候,在内核空间,VFS就会调用各文件系统定义的对应操作函数。
FUSE内核模块中被定义的操作函数把和它对应的请求送到实现文件系统的用户空间进程(FUSE文件系统,也就是后台程序),并等待回应。
FUSE内核模块和FUSE文件系统间的通信是通过设备文件/dev/fuse进行的。
FUSE文件系统把定义的FUSE操作函数群的地址登录到fuse_operations结构体中,并通过把fuse_operations的地址作为参数,调fuse_main()函数
以下的图指出在example/hello的例子中,文件系统调用的路径。
1.打开设备文件/dev/fuse
2.挂载FUSE文件系统
3.做成FUSE文件系统句柄
4.登录FUSE操作函数到FUSE文件系统句柄中
5.登录信号处理器
6.执行事件循环
A)从设备文件/dev/fuse中读取来自内核模块的请求
B) 执行和这个请求对应的操作函数
C) 写入返回给内核模块的应答到设备文件/dev/fuse中
7.卸载FUSE文件系统
在库函数fuse_main()中,执行以下的动作。
API库里定义的接口如getattr,mknod,mkdir,unlink等包含在./include/fuse.h头文件里。
2.3解压FUSE
要开发一个文件系统,首先请下载FUSE的源代码并展开这个包:
tar-zxvffuse-2.7.0.tar.gz。
这会创建一个FUSE目录,其中保存的是源代码。
fuse-2.7.0目录的内容如下:
./doc包含了与FUSE有关的文档。
现在,这只有一个文件how-fuse-works。
./kernel包含了FUSE内核模块的源代码(对于使用FUSE开发文件系统来说,您当然不用懂得这些代码的机制)。
./include包含了FUSEAPI头,您需要这些文件来创建文件系统。
您现在唯一需要的就是fuse.h。
./lib中存放的是创建FUSE库的源代码,您需要将它们与您的二进制文件链接在一起来创建文件系统。
./util中存放的是FUSE工具库的源代码。
./example当然包含的是一些供您参考的例子,例如fusexmp.null和hello文件系统。
2.4编译并安装FUSE
在fuse-2.7.0目录中运行configure脚本:
./configure。
这会创建所需要的makefile等内容。
运行./make来编译库、二进制文件和内核模块。
查看kernel目录中的文件./kernel/fuse.ko——这是内核模块文件。
还要查看lib目录中的fuse.o、mount.o和helper.o。
运行./makeinstall完成FUSE的安装。
重要提示:
在编译FUSE时,系统中需要有内核头文件或源代码。
为了简单起见,请确保将内核源代码放到/usr/src/目录中。
3主要思想和技术路线
3.1数据结构定义
u_fs文件系统使用一个镜像文件(本机测试为ufs_iso文件),空间分配如下。
Superblock
(1block)
Bitmapblock
(1280blocks)
Datablock
(alltherestblocks)
测试时分配了1K*5K=5M空间,共10240块。
超级块superblock
超级块一定是文件系统的第一块,描述了整个文件系统,结构定义如下:
structsb{
longfs_size;//整个文件系统的块数
longfirst_blk;//根目录所在的第一块
longbitmap;//位图块大小
}
目录Directory
目录应看做文件。
每个目录下包含一个u_fs_directory_entry结构的表。
在本文件系统没有对目录个数作出限制,但要注意文件名不得超过8字节,拓展名不超过3字节。
structu_fs_file_directory{
charfname[MAX_FILENAME+1];//文件名
charfext[MAX_EXTENSION+1];//拓展名
size_tfsize;//大小
longnStartBlock;//起始块
intflag;//类型:
0-未使用1-文件2-目录
}
文件Files
文件存储在单一、预分配的虚拟磁盘上,每个虚拟块大小为512字节。
structu_fs_disk_block{
size_tsize;//该块用了多少字节
longnNextBlock;//下一块的指针
chardata[MAX_DATA_IN_BLOCK];//可用的虚拟存储空间
};
3.2主要函数定义
3.2.1.u_fs函数定义
fuse_operation结构中用到的函数
structfuse_operations{
int(*getattr)(constchar*,structstat*);
int(*readdir)(constchar*,fuse_dirh_t,fuse_dirfil_t);
int(*mknod)(constchar*,mode_t,dev_t);
int(*mkdir)(constchar*,mode_t);
int(*unlink)(constchar*);
int(*rmdir)(constchar*);
int(*open)(constchar*,structfuse_file_info*);
int(*read)(constchar*,char*,size_t,off_t,structfuse_file_info*);
int(*write)(constchar*,constchar*,size_t,off_t,structfuse_file_info*);
int(*flush)(constchar*,structfuse_file_info*);
int(*truncate)(constchar*,off_t);
int(*init)(structfuse_conn_info*);
};
int(*getattr)(constchar*,structstat*);
/*这个函数与stat()类似。
st_dev和st_blksize域都可以忽略。
st_ino域也会被忽略,除非在执行mount时指定了use_ino选项。
*/
int(*readdir)(constchar*,fuse_dirh_t,fuse_dirfil_t);
/*这个函数会读取一个目录中的内容。
这个操作实际上是在一次调用中执行opendir()、readdir()、closedir()序列。
对于每个目录项来说,都应该调用filldir()函数。
*/
int(*mknod)(constchar*,mode_t,dev_t);
/*这个函数会创建一个文件节点。
此处没有create()操作;mknod()会在创建非目录、非符号链接的节点时调用。
*/
int(*mkdir)(constchar*,mode_t);
int(*rmdir)(constchar*);
/*这两个函数分别用来创建和删除一个目录。
*/
int(*unlink)(constchar*);
/*这个函数用来删除一个文件。
*/
int(*open)(constchar*,structfuse_file_info*);
/*这是文件的打开操作。
对open()函数不能传递创建或截断标记(O_CREAT、O_EXCL、O_TRUNC)。
这个函数应该检查是否允许执行给定的标记的操作。
另外,open()也可能在fuse_file_info结构中返回任意的文件句柄,这会传递给所有的文件操作。
)*/
int(*read)(constchar*,char*,size_t,off_t,structfuse_file_info*);
/*这个函数从一个打开文件中读取数据。
除非碰到EOF或出现错误,否则read()应该返回所请求的字节数的数据;否则,其余数据都会被替换成0。
一个例外是在执行mount命令时指定了direct_io选项,在这种情况中read()系统调用的返回值会影响这个操作的返回值。
*/
int(*write)(constchar*,constchar*,size_t,off_t,structfuse_file_info*);
/*这个函数将数据写入一个打开的文件中。
除非碰到EOF或出现错误,否则write()应该返回所请求的字节数的数据。
一个例外是在执行mount命令时指定了direct_io选项(这于read()操作的情况类似)。
*/
int(*flush)(constchar*,structfuse_file_info*);
/*这表示要刷新缓存数据。
它并不等于fsync()函数——也不是请求同步脏数据。
每次对一个文件描述符执行close()函数时,都会调用flush();因此如果文件系统希望在close()中返回写错误,并且这个文件已经缓存了脏数据,那么此处就是回写数据并返回错误的好地方。
由于很多应用程序都会忽略close()错误,因此这通常用处不大。
*/
int(*truncate)(constchar*,off_t);
/*这个函数用来修改文件的大小。
*/
int(*init)(structfuse_conn_info*);
/*这个函数用来对加载的文件系统初始化,如:
获得文件系统的大小。
*/
3.2.2.base函数定义
为u_fs的FUSE用户操作提供底层操作,在base.c定义供u_fs调用。
intop_read_blk(longblk,u_fs_disk_block*content);
//读取块中的内容
intop_write_blk(longblk,u_fs_disk_block*content);
//往块中写入内容
intop_search_free_blk(intnum,long*start_blk);
//寻找空闲块,采用首次匹配法
intop_set_blk(longblk,intflag);
//设置块的flag位
intop_create(constchar*,intflag);
op_create()
//函数把创建目录和文件统一起来。
intop_open(constchar*org_path,u_fs_file_directory*attr);
op_open()
/*返回要打开的目录或文件的u_fs_file_directory记录,根据此记录可以知道目录或文件所在的数据块,大小等属性,以备调用的函数使用。
*/
intop_setattr(constchar*org_path,u_fs_file_directory*attr);
op_setattr()
/*更改文件或目录的u_fs_file_directory记录。
在删除文件或目录,使用此函数可使flag设为0。
在写文件时,调用此函数可以更改文件的大小。
*/
intop_rm(constchar*path,intflag);
op_rm()
/*函数把删除目录和文件统一起来。
删除时,要把对应的数据块释放;把u_fs_file_directory记录的flag标记为0。
*/
4测试结果
注意:
cy采用宏定义,即在u_fs.h里对路径进行定义。
现定义为#defineUFS_ISO“/home/chenyue/aimao/ufs_iso”
此值应根据不同系统改成对应的绝对路径。
4.1创建文件系统
1.分配磁盘空间
ddbs=1Kcount=5Kif=/dev/zeroof=./ufs_iso
2.格式化磁盘空间
./u_fs_init
3.创建装载位置
mkdircy装载ufs_iso文件系统到cy文件夹,发现在位置一栏新增了“cy”盘。
./u_fscy
4.查看cy文件夹内容,发现为空
ls–alcy
4.2文件夹测试
5.进入文件系统
cdcy
6.创建超长文件夹,操作不允许
mkdirabcdefighijk
7.创建普通文件夹
mkdirrootdir
8.进入刚创建的dir文件夹
cdrootdir
9.创建子文件夹,操作不允许
mkdirleftdir
4.3文件测试
10.退回到根目录,查看不存在的文件,提示错误
cd..
catfile
11.创建并编辑文件,添加“Hello,world!
!
!
”内容
gedithello
12.查看hello文件
cathello
13.测试获取文件列表的功能
ls–al
14.删除不存在的文件nofile
rmnofile
15.删除存在的文件hello,并查看
rmhello
ls–al
4.4格式化功能测试
16.回到文件系统父目录,查看已有文件
ls–alcy
17.格式化
./u_fs_init
18.再次查看,发现已经清空
ls–alcy
4.5卸载文件系统
19.卸载文件系统
fusermount–ucy
文件系统已经卸载
5源代码的目录结构及存放位置
源码包含:
u_fs.h
包含数据结构定义及各种常数
u_fs_inti.c
提供格式化操作
bottom.c
对bottom.h的底层函数进行定义
bottom.h
提供底层函数供u_fs.c调用
u_fs.c
文件系统的主函数
makefile
提供编译、卸载的功能
6运行环境
系统:
Ubuntu9.04
编译器:
gcc
附加库:
fuse-2.7.0