简单多用户文件系统.docx
- 文档编号:5689828
- 上传时间:2023-05-09
- 格式:DOCX
- 页数:19
- 大小:101.70KB
简单多用户文件系统.docx
《简单多用户文件系统.docx》由会员分享,可在线阅读,更多相关《简单多用户文件系统.docx(19页珍藏版)》请在冰点文库上搜索。
简单多用户文件系统
简单多用户文件系统
一、课程设计任务描述
为LINUX设计一个简单的二级文件系统。
要求做到以下几点:
1、可以实现下列几条命令
Login
用户登录
Dir
列文件目录
Create
创建文件
Delete
删除文件
Open
打开文件
Close
关闭文件
Read
读文件
Write
写文件
2、列目录时要列出文件名、物理地址、保护码和文件长度。
3、源文件可以进行读写保护。
二、设计思想说明
2.1对该任务的理解分析
一个文件系统从功能上划分程序为四个部分,第一部分是有关高速缓冲区的管理程序,主要实现了对硬盘等块设备进行数据高速存取的函数;第二部分代码描述了文件系统的底层通用函数,说明了文件索引节点的管理、磁盘数据块的分配和释放以及文件名与i节点的转换算法;第三部分程序是有关对文件中数据进行读写操作,包括对字符设备、管道、块读写文件中数据的访问;第四部分的程序与文件的系统调用接口的实现有关,主要涉及文件打开、关闭、创建以及有关文件目录操作等的系统调用。
由于我们不能亲自设计驱动程序,所以我们要模拟文件系统的设计、实现和功能,就不能把它直接做为操作系统实际的文件系统进行挂接。
鉴于此,我们就有两个思路来完成该任务,一是在实际的硬盘上创建一个文件,把它做为磁盘进行各种对磁盘的模拟操作,这样做的好处是可以对它进行连续操作,只要在退出文件系统时,及时保存它的状态,当我们下次启动程序时,就能继续以前的操作,相比而言这更接近于实际;二是在内存中开辟一块空间,譬如1M或2M大小,继而对这块内存区域模拟磁盘操作,操作灵活但这样需每次开辟空间,极有可能隐藏一些需要关闭文件系统才能发现的错误,也就是说这样做不易于排错。
在本次的课程设计中,我们决定采用第一种方案。
由于是在文件级上的操作,所以我们不必去写设备驱动程序,只需要开辟文件调用fwrite、fread、fseek、ftell、fput、fget等库函数进行读写即可。
在文件系统四部分程序中,我们只需要编写第二部分文件系统的底层通用函数即可。
2.2设计任务剖析
在本次的课程设计中,我们没有沿用《课程设计指导书》上文件系统的例子程序,而是决定模拟Linux的标准根文件系统EXT2,其原因我们会在课程设计总结中给出。
我们认为EXT2主要的设计思想是磁盘分区再分组,数据存储使用混合索引方式。
这也是我们要实现的主要功能。
在参考了Linux0.11文件系统Minix2.0及Linux2.4EXT2的底层通用函数后,本着设计简单可表达EXT2设计思想的原则,我们需要编写的程序要实现下列功能:
●格式化程序。
在硬盘上创建一个文件,用来模拟磁盘;对磁盘按照EXT2文件系统结构进行划分;主要数据的写入,包括根目录、登陆文档、超级块、组描述符的初始化及组描述符表、块位图索引节点位图的初始化及索引节点表。
●磁盘读写函数。
这部分的函数要完成的功能包括:
读写指定的磁盘块;读写指定的索引节点表和块位图;读写指定的超级块和组描述符。
●数据块分配和回收函数。
按照先组从小到大,后逻辑块编号从小到大的顺序分配数据块;回收指定的逻辑块改写相应组内的块位图。
●索引节点分配和回收。
按照先组从小到大,后索引编号从小到大的顺序分配索引节点;回收指定的索引节点改写相应组内的索引节点位图。
●目录操作函数。
列表显示当前目录内目录项,更改目录及删除目录。
●文件操作函数。
组织进程和文件系统的关系,包括用户打开文件表和系统打开文件表的初始化和管理。
创建文件、删除文件、打开文件、关闭文件、读文件和写文件。
程序是引用文件描述符来操作文件的。
●用户认证。
读取文件系统的密码文档,对登陆用户验证。
由于EXT2文件系统是相对较大的程序的组合,在较短的时间内很难全面模仿,所以我们对它在不改变其主要设计思想的基础上,进行了适当简化。
编写程序时主要遵循的设计思想如下:
●设置全局宏定义。
在实际中,文件系统要引用一些常量,是在各种数据结构体中查找的,而我们为了使得程序设计的简单,使用了全局的宏定义,在程序的任何地方都可方便的使用。
●数据分配采用混合索引方式。
在数据块的组织上我们使用EXT2的混合索引方式,但我们不准备照搬EXT2的方式,而是把数据指针定为5个,前4个作为直接指针,第5个做为单级指针。
这样我们文件系统中文件最大就定为了:
(BLOCKSIZE_BT是以字节表示的磁盘块大小)
4*BLOCKSIZE_BT+(BLOCKSIZE_BT/4)*BLOCKSIZE_BT
=4*512B+(512/4)*512B
=67584B=67584B/(1024B/K)
=66KB
●目录采用直接指针方式。
在创建目录项时,我们把这5个数据指针都作为了直接指针。
那么每个目录可包含的目录项为:
5*(BLOCKSIZE_BT/DIR_ENTRY_LEN)=40
●在进程和文件系统的关系上,使用了EXT2的组织方式,可用下图表示:
2.3程序设计环境及工具选择
该试验程序是小组成员在Windows2000平台下,使用MicrosoftVisualC++6.0编辑、编译及调试通过的。
之所以选择这种组合是在考虑了Windows平台的易用性、广泛性和程序文件转储简单等特性,另外VisualC++可自己组织程序的调用和编译,省去了在Linux平台下使用GNU/GCC书写Makefile文件系统的麻烦。
这样可以在较短的时间内完成文件系统复杂程序的编写。
考虑到VisualC++是32位的编译器,为了在其他一些16位编译器如TC下编译通过,我们特意为此设计了通用模式。
关于此下文有详细的说明。
2.4函数层次图(即模块关系图)
图例说明:
为shell调用命令
为程序调用函数
三、EXT2文件系统简介
3.1文件系统概述
简单地说,文件系统就是操作系统与存储介质之间交换数据的一种协议约定,它对文件的组织和存取规则进行详细描述,同时保证数据的完整性。
有了这种逻辑上的约定,文件系统就不必了解数据块的物理存储位置,它只需保存逻辑块的编号,而对磁盘的物理操作是由文件系统磁盘函数库(DiskLibrary)中的各种底层函数,通过块设备驱动程序,来完成由逻辑块编号到物理存储位置的转换。
3.2EXT2文件系统简介
Linux第一版的文件系统来自Minix,随着Linux的逐步成熟,从而为Linux量身定做了EXT文件系统,但其性能差强人意,并不能满足实际的需要。
1993年由RemyCard做了进一步改良,EXT演变为EXT2,它同样是建立在文件的数据以数据块为组织单位的前提下。
因其高效和强健的特性,成为了Linux内核使用的标准根文件系统。
EXT2的英文全称是SecondExtrendedFileSystem,亦即第二扩展文件系统的意思,它负责管理系统外存上的文件,为操作系统和用户提供对文件的存取、共享和保护的手段。
Ext2的优点是:
●支持达4TB的内存。
●文件名称最长可以到1012个字符。
●当创建文件系统时,管理员可以选择逻辑块的大小(通常大小可选择1024、2048和4096字节)。
●实现快速符号链接:
不需要为此目的而分配数据块,并且将目标名称直接存储在索引节点(inode)表中。
这使性能有所提高,特别是在速度上。
因为Ext2文件系统的稳定性、可靠性和健壮性,所以几乎在所有基于Linux的系统(包括台式机、服务器和工作站—并且甚至一些嵌入式设备)上都使用Ext2文件系统。
然而,当在嵌入式设备中使用Ext2fs时,它有一些缺点:
Ext2是为象IDE设备那样的块设备设计的,这些设备的逻辑块大小是512字节,1K字节等这样的倍数。
这不太适合于扇区大小因设备不同而不同的闪存设备。
Ext2文件系统没有提供对基于扇区的擦除/写操作的良好管理。
在Ext2中,为了在一个扇区中擦除单个字节,必须将整个扇区复制到RAM,然后擦除,然后重写入。
考虑到闪存设备具有有限的擦除寿命(大约能进行100,000次擦除),在此之后就不能使用它们,所以这不是一个特别好的方法。
在出现电源故障时,Ext2fs不是防崩溃的。
Ext2文件系统不支持损耗平衡,因此缩短了扇区/闪存的寿命。
(损耗平衡确保将地址范围的不同区域轮流用于写和/或擦除操作以延长闪存设备的寿命。
)Ext2fs没有特别完美的扇区管理,这使设计块驱动程序十分困难。
EXT2把硬盘分成多个分区,通常必须有一个主分区(Native)和一个交换分区(Swap),Linux把每一个分区都当作一个独立的设备对待。
主分区的大部分空间用来存储系统中的各种数据,例如普通文件、目录文件等文件,少部分用来定义文件系统的数据结构;交换分区用作系统的虚拟内存。
实际上每个分区都是一个文件系统,有它们各自的顶层目录和下面的目录层次结构。
这些单独的文件系统按照一定的挂接方式形成一个总的目录层次结构。
逻辑分区继续分成多个块组(blockgroup),块组下面又分为超级块(SuperBlock)、组描述符表(groupdescriptors)、块位图(Bitmap)、索引节点(inode)位图、索引节点表、目录块和数据块等,它们各自占有不同数量的逻辑块,在文件系统中起着不同的作用。
在块组0之前还有一个引导块,它位于任何EXT2分区中的第1块,是为分区的启动扇区保留的,不受Ext2文件系统的管理。
若该分区为系统的主引导分区时,引导块的内容就为引导信息含有可执行代码,否则为空。
在同一个文件系统中,数据块的大小是固定的,对于不同的EXT2文件系统这个值可以不同。
数据块的大小是在建立EXT2文件系统时,由系统管理员指定或由文件系统的创建程序根据硬盘分区的大小,自动选择一个较合理的值确定的,这个值一经确定,文件系统就把它作为基本参数保存起来,在运行期间就不会改动了。
以后文件所需的存储空间就依照这个指定大小的数据块为基本单位进行分配。
EXT2文件系统的逻辑硬盘布局
在每个块组中重复保存着相对于其分区文件系统的一些重要信息,包括一份超级块的拷贝和一组块组描述符的拷贝。
这种对文件系统完整性关键信息的重复保存,虽然浪费了一些存储空间,但有助于文件系统在发生故障时的还原。
实际上只有块组0中所包含的超级块和组描述符才被内核读取使用,其余的拷贝信息一般保持不变,只有当出现数据损坏,并且块组0中的主超级块和主描述符表变为无效时,才被文件系统引用,通过e2fsck程序把Ext2分区恢复到某个一致的状态。
四、数据设计与表示
4.1头文件说明
4.1.1头文件:
types.h
#ifndef_I386_TYPES_H
#define_I386_TYPES_H
#defineVARTYPE1//1为在vc下编译
#ifVARTYPE==1
typedefunsignedint_U32;
typedefunsignedshort_U16;
typedefunsignedchar_U8;
typedefint_S32;
typedefshort_S16;
typedefchar_S8;
#else
typedefunsignedlong_U32;
typedefunsignedint_U16;
typedefunsignedchar_U8;
typedeflong_S32;
typedefint_S16;
typedefchar_S8;
#endif
#endif
因为在16位和32位的编译器下表达int的字节是不同的,而在写各种数据块时又必须按照字节对应写入,这就照成了程序的不能通用。
鉴于此,我们使用typedef命令把数据类型进行了规定。
4.1.2头文件:
filetype.h
#ifndef__FILETYPE__
#define__FILETYPE__
#defineUKN0x0000//0未知
#defineREG0x0001//1普通文件
#defineDIR0x0002//2目录文件
#defineCHR0x0003//3字符设备
#defineBLK0x0004//4块设备
#defineFIFO0x0005//5命名管道
#defineSOCK0x0006//6套接字
#defineLNK0x0007//7符号链接
#defineS_IREG(flag)(flag==0x01)?
REG:
0//1判断普通文件
#defineS_IDIR(flag)(flag==0x02)?
DIR:
0//2判断目录文件
#defineS_ICHR(flag)(flag==0x03)?
CHR:
0//3判断字符设备
#defineS_IBLK(flag)(flag==0x04)?
BLK:
0//4判断块设备
#defineS_IFIFO(flag)(flag==0x05)?
FIFO:
0//5判断命名管道
#defineS_ISOCK(flag)(flag==0x06)?
SOCK:
0//6判断套接字
#defineS_ILNK(flag)(flag==0x07)?
LNK:
0//7判断符号链接
#endif
按照UNIX的文件属性设置定义该头文件,及用来对文件属性的判断。
4.1.3头文件:
sys.h
该头文件包括了系统使用的各种宏定义和数据结构,这部分的内容将在“数据结构说明”和“宏定义说明”部分予以介绍。
4.2数据结构说明
4.2.1超级块(superblock)
超级块位于每个块组的最前面,如前所述对于每个块组其内容是相同的,在任何一个块组中超级块只占用1个数据块。
它是用来描述EXT2文件系统整体布局信息的数据结构,包含其所在分区文件系统目录和文件的静态分布情况,并给出文件系统各组成部分的大小和形状等信息。
structext2_super_block{
_U32s_inodes_count;/*索引节点的总数Inodescount*/
_U32s_blocks_count;/*以块为单位的文件系统的大小Blockscount*/
_U32s_free_blocks_count;/*空闲块计数器Freeblockscount*/
_U32s_free_inodes_count;/*空闲索引节点计数器Freeinodescount*/
_U32s_first_data_block;/*第一个使用的块号FirstDataBlock*/
_U32s_log_block_size;/*块的大小Blocksize*/
_U32s_blocks_per_group;/*每组中的块数Blockspergroup*/
_U32s_inodes_per_group;/*每组中的节点数Inodespergroup*/
_U32s_mtime;/*最后一次安装操作的时间Mounttime*/
_U32s_wtime;/*最后一次写操作的时间Writetime*/
_U16s_magic;/*魔数签名Magicsignature*/
_U32s_first_ino;/*第一个非保留的索引节点号*/
_U16s_inode_size;/*磁盘上索引节点结构的大小*/
};
#defineSUPER_BLOCK_LENsizeof(structext2_super_block)//56B
4.2.2组描述符
在设计上Linux深受BSDFFS(快速文件系统)的影响,它的块组与FFS的柱面组很类似。
然而,块组与磁盘上块的物理布局没有关系,因为现代驱动器趋向于顺序访问优化设计,并向操作系统隐藏了其中的物理几何参数。
这个结构也同样在性能上带来好处:
通过减少i节点表与数据块之间的距离,就有可能降低磁头对文件I/O操作寻道的时间,从而提高了文件存取的效率。
分区在逻辑上把块组看作是一个线性数组,所含块组的数量取决于该分区的大小和预设的块的大小,主要限制在于块位图。
每个块组中的块位图必须存放在1个单独的块中,用来标识一个组中块的占用和空闲状况。
在数据块的大小确定以后,每个块组的大小也同时被固定了下来,由下面的公式可以得到一组重要的信息:
设数据块及分区容量分别为:
NKBSKB
每组中含数据块的最大数:
DBMAX=N*1024*8=8192*N
块组最大容量:
BGSIZE=DBMAX*N=8192*N2
分区中块组最小数:
BGMIN=S/DBSIZE=S/(8192*N2)
每个块组与一个组描述符(ext2_group_desc,见\include\linux\ext2_fs.h)对应,组描述符记录该块组的一些重要信息的位置以及该块组的空间使用情况,
structext2_group_desc
{
_U32bg_block_bitmap;/*块位图的块号*/
_U32bg_inode_bitmap;/*索引节点位图的块号*/
_U32bg_inode_table;/*第一个索引节点表块的块号*/
_U16bg_free_blocks_count;/*组中空闲块的个数*/
_U16bg_free_inodes_count;/*组中索引节点的个数*/
_U16bg_used_dirs_count;/*组中目录的个数*/
_U16bg_id;/*该组描述副的编号*/
_U32bg_reserved[3];/*填充字符*/
};
#defineGROUP_DESC_LENsizeof(structext2_group_desc)//32B
4.2.3磁盘索引节点
structext2_inode{
_U16i_mode;/*文件类型和访问权限*/
_U16i_uid;/*拥有者标识符*/
_U32i_size;/*以字节为单位的文件长度*/
_U32i_atime;/*最后一次访问文件的时间*/
_U32i_ctime;/*索引节点最后改变的时间*/
_U32i_mtime;/*文件内容最后改变的时间*/
_U32i_dtime;/*文件删除的时间*/
_U16i_gid;/*组标识符*/
_U16i_links_count;/*硬链接计数器*/
_U32i_blocks;/*文件的数据块数*/
_U32i_flags;/*文件标志*/
_U32i_block[EXT2_N_BLOCKS];/*指向数据块的指针*/
_U32re[2];
};
#defineINODE_LENsizeof(structext2_inode)//64
4.2.4内存索引节点
structext2_inode_info{
structext2_inode_info*i_next;
structext2_inode_info*i_pri;
_U16i_mode;/*文件类型和访问权限*/
_U32i_data[EXT2_N_BLOCKS];/*逻辑块指针*/
_U32i_count;/*内存关联文件数*/
_U32i_inode;/*索引接点编号*/
_U8i_dirty;/*脏数据*/
_U32i_links_count;/*硬链接计数器*/
_U16i_blocks;/*文件大小(以块表示)*/
_U32i_size;/*以字节为单位的文件长度*/
_U16i_uid;/*拥有者标识符*/
_U32i_atime;/*最后一次访问文件的时间*/
_U32i_ctime;/*索引节点最后改变的时间*/
_U32i_mtime;/*文件内容最后改变的时间*/
_U32i_dtime;/*文件删除的时间*/
};
#defineINODE_INFO_LENsizeof(structext2_inode_info)
4.2.5磁盘目录项结构体
在ext2文件系统中,目录文件包含有下属文件与子目录的登记项。
当创建一个文件时,就构成一个目录项,并添加到相应的目录文件中。
一个目录文件可以包含很多目录项,每个目录项(如ext2文件系统的ext2_dir_entry_2)包含的信息如下:
(1)索引节点号。
这是相应文件在数据块组中的索引节点号码,即检索索引节点表数组的索引值。
(2)目录项长度。
记载该目录项占多少字节。
(3)名字长度。
记载相应文件名的字节数。
(4)文件类型。
用一个数字表示文件的类型,例如,1表示普通文件,2表示目录,3表示字符设备文件,4表示块设备文件等。
(5)文件名字。
文件名(不包括路径部分)的最大长度为255个字符。
每个目录的前两个目录始终是标准的“.”和“..”,它们分别代表目录自身和其父目录。
当用户需要打开某个文件时,首先要指定该文件的路径和名称,文件系统根据路径和名称搜索对应的索引节点,找到该文件的数据块,从而读取文件中的数据。
structext2_dir_entry{
_U32inode;/*索引节点号Inodenumber*/
_U16rec_len;/*目录项的长度Directoryentrylength*/
_U16file_type;/*文件类型*/
charname[EXT2_NAME_LEN];/*文件名Filenamelength*/
};
#defineDIR_ENTRY_LENsizeof(structext2_dir_entry)//64B
4.2.6当前目录结构体
structfs_struct{
_U32count;
_U32lock;
_U32umask;
structext2_inode_info*root,*pwd;
chard_pwd[EXT2_NAME_LEN],d_root[EXT2_NAME_LEN];
};
#defineFS_STRUCT_LENsizeof(structfs_struct)
4.2.7用户打开文件表结构体
structfiles_struct{
_U32count;
_U32file_lock;/*Protectsallthebelowmembers.Nestsinsidetsk->alloc_lock*/
_S32max_fds;
_S32max_fdset;
_S32next_fd;
structfile**fd;/*currentfdarray*/
structfile*fd_array[NR_OPEN_DEFAULT];
};
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 简单 多用户 文件系统