1.42k likes | 1.71k Views
第 9 章 文件系统. 文件系统的选择是系统能够正常运行的基本条件。 使用了某种文件系统,就必须遵守其中的规则,否则,您在使用计算机的过程中就会遇到一些问题。. 本章主要介绍了: ◆ Linux 的文件系统结构。 ◆ Linux 采用的 VFS ,支持如 romfs 、 ramfs 、 ex2 、 jffs2 、 ms-dos 、 nfs 等各种文件系统。 ◆ Linux 源程序和开发板根文件系统 romfs 的目录结构和功能描述。 ◆ 在 uClinux 中文件的打开和读写操作示例。. 9.1 文件系统结构.
E N D
文件系统的选择是系统能够正常运行的基本条件。文件系统的选择是系统能够正常运行的基本条件。 使用了某种文件系统,就必须遵守其中的规则,否则,您在使用计算机的过程中就会遇到一些问题。
本章主要介绍了: ◆ Linux的文件系统结构。 ◆ Linux采用的VFS,支持如romfs、ramfs、ex2、jffs2、ms-dos、nfs等各种文件系统。 ◆ Linux源程序和开发板根文件系统romfs的目录结构和功能描述。 ◆ 在uClinux中文件的打开和读写操作示例。
9.1 文件系统结构 文件系统是操作系统的重要组成部分。 Linux特性之一就是对多种文件系统的 支持。 这种特性使得Linux很容易地同其他操作 系统共存。
文件系统的概念使得用户能够查看存储设备上的文件和路径而无须考虑实际物理设备的文件系统类型。文件系统的概念使得用户能够查看存储设备上的文件和路径而无须考虑实际物理设备的文件系统类型。 Linux透明的支持许多不同的文件系统,将各种安装的文件和文件系统以一个完整的虚拟文件系统的形式呈现给用户。
Linux在早期采用的是minix文件系统,但minix只是一种教学型的文件系统,它所管理的文件系统最大为64MB,文件名小于14个字符。Linux在早期采用的是minix文件系统,但minix只是一种教学型的文件系统,它所管理的文件系统最大为64MB,文件名小于14个字符。 目前Linux中,使用的主流文件系统是Ext2/3。
除Ext2/3以外,在Linux发展过程中,设计人员比较早的考虑到了对其他类型文件系统的支持。除Ext2/3以外,在Linux发展过程中,设计人员比较早的考虑到了对其他类型文件系统的支持。 要实现这一目的,需要将它们的操作和管理纳入统一的框架当中来,使得内核的文件系统接口,如同标准的的文件系统“总线”,让用户通过同一组系统调用来管理和操作不同类型文件系统上的文件。
这个统一的、抽象的、虚拟的文件系统接口,被称为VFS(virtual FileSystem Switch),它主要包含一组标准的文件操作接口。 通过VFS,用户看到的都是一个个的VFS文件,忽略了文件本身所处文件系统的差别。
将内核比作计算机主板,那么VFS就是一种标准的系统总线,各种文件系统就是插在该总线上的子卡,虽然各个子卡的内部线路不同,但在总线接口处一致。将内核比作计算机主板,那么VFS就是一种标准的系统总线,各种文件系统就是插在该总线上的子卡,虽然各个子卡的内部线路不同,但在总线接口处一致。 同时,内核看到的所有子卡的特性也映射为具有共性的几类。 如图9-1所示。
目前Linux系统支持的文件系统种类很多,包括: ntfs(windows NT的文件系统), msdos(dos的文件系统), isofs(光盘文件系统), nfs(网络文件系统),
romfs(rom中的文件系统), smbfs(即samba,可以在网络中与 win98、winnt共享), proc(目录/proc下的特殊文件系统), jffs(flash中的文件系统)。
当用户访问一个磁盘文件系统时,对于目录树下的访问,最终将转换成对于这一部分物理磁盘的访问。当用户访问一个磁盘文件系统时,对于目录树下的访问,最终将转换成对于这一部分物理磁盘的访问。 对于设备文件的访问,最终将转换成对于对于驱动程序的访问。
对于其他特殊文件的访问,一般是在Linux的内存数据结构中完成的。对于其他特殊文件的访问,一般是在Linux的内存数据结构中完成的。 对于磁盘文件系统中的文件的访问和磁盘设备文件的访问最终都反应在磁盘驱动程序上,它们有什么不同吗?
对于磁盘文件系统中文件的访问,是在文件目录树的结构下,对于有组织的数据进行的;对于磁盘文件系统中文件的访问,是在文件目录树的结构下,对于有组织的数据进行的; 而对磁盘设备文件进行访问,则是对于线性空间内数据的访问,也就是无法看到数据的组织情况。 文件系统的层次结构如图9-2所示。
9.2 文件系统类型 在uClinux的系统中,由于硬件资源和使用环境的限制,一般内存的数量比较小(8~32M字节),外存只配置小容量的FLASH;所以,在uClinux中,比较常用的文件系统有romfs文件系统,虚拟ramdisk,JFFS文件系统。 对于有网络设备的系统,还可以使用NFS文件系统。
9.2.1 romfs文件系统 1. romfs特点 romfs(rom file system)是一种只读文件系统,占用系统资源也比较小。
起初,设计它的目的是在启动盘(包括光盘和软盘)等场合下,提供一个比普通文件系统(如功能强大的ext2)更加节省空间的文件系统。起初,设计它的目的是在启动盘(包括光盘和软盘)等场合下,提供一个比普通文件系统(如功能强大的ext2)更加节省空间的文件系统。 创建romfs文件系统需要使用genromfs工具。
目前romfs已经获得了广泛的应用,日趋成熟。 根据romfs开发者的介绍,如果把文件系统编译成为Linux的一个内核module进行加载,那么minix文件系统编译出来的module的大小将会超过20KB(经测试在2.4.7内核中编译出来的minix.o是33909字节),而采用i586编码(即在普通奔腾机上)的romfs的module可以不超过1个代码页即4KB(测试结果2.4.7内核中是7501字节,超过了4KB)。
此外虽然Linux下的msdos文件系统根本就未支持设备文件和符号链接,msdos文件系统在kernel 2.4.7下编译出来的module(msdos.o)大小仍然达到了10670B。
从上面的比较可以看出,在romfs中,文件系统的管理代码占用的空间比较小,这—点就可以从一个方面看出romfs比较节省空间。从上面的比较可以看出,在romfs中,文件系统的管理代码占用的空间比较小,这—点就可以从一个方面看出romfs比较节省空间。
需要注意的是,romfs的文件访问权限和属主这些信息尚没有完全实现。需要注意的是,romfs的文件访问权限和属主这些信息尚没有完全实现。 此外,由于romfs文件系统是只读的,所以可以做得很小。但是有不少场合,还需要对其进行写操作。 要满足这些写操作的要求,只能在编译的时候加上写访问功能,或者采取变通的手段,在运行的时候另外生成一个RAMdisk宋暂存数据。
2. romfs文件系统结构 romfs文件系统是为了对块设备进行高效管理而开发的。所有的romfs文件,经过genromfs程序生成之后,合并到一个文件(即romfs的映象文件)中去。
只需要采用mount命令将这个文件挂接到任何一个目录下,就可以对这个romfs中的文件按照正常方式进行访问了。只需要采用mount命令将这个文件挂接到任何一个目录下,就可以对这个romfs中的文件按照正常方式进行访问了。 romfs映像文件的文件组织方式如表9-1所示。
romfs映像文件开始的8个字节存放了ASCII码“-ROM1FS-”,之后存放了这个文件系统中的字节总数。romfs映像文件开始的8个字节存放了ASCII码“-ROM1FS-”,之后存放了这个文件系统中的字节总数。 checksum处存放的是从文件头开始的512个字节的校验码。然后是文件系统的卷标名称,该名称以ASCII值为0的字符结尾,所占用的空间为16字节的整数倍。 后面就开始存放各个文件的头部结构了。 文件的表示结构如表9-2所示。
其中,spec.info域根据该文件(或者目录)的类别而有不同的含义。其中,spec.info域根据该文件(或者目录)的类别而有不同的含义。 主要有如下几种情况:
0:硬链接,此时spec.info域的内容为用于链接的目标文件 0:硬链接,此时spec.info域的内容为用于链接的目标文件 1:目录,此时spec.info域的内容为第一个文件的文件头 2:普通文件,此时spec.info域的内容无效,应该设置为0值 3:符号链接,此时spec.info域的内容无效,应该设置为0值
4:块设备,此时spec.info域的内容为16bit的主设备号和16bit的从设备号 4:块设备,此时spec.info域的内容为16bit的主设备号和16bit的从设备号 5:字符设备,同样,此时spec.info域的内容无效,应该设置为0值 6:网络socket套接字,此时spec.info域的内容无效,应该设置为0值 7:fifo管道文件,此时spec.info域的内容无效,应该设置为0值
由于romfs文件系统为了减小module的大小省略了很多完整性检测的代码,所以使用者要自己注意,如不要生成硬链接循环,要自己为当前目录和父目录生成“.”和“..”链接。由于romfs文件系统为了减小module的大小省略了很多完整性检测的代码,所以使用者要自己注意,如不要生成硬链接循环,要自己为当前目录和父目录生成“.”和“..”链接。 当然,这些工作genromfs工具通常都会自动做好的。
3. romfs使用 EV44B0II的romfs的制作过程如图9-3所示。
(1) 在主机的/romfs目录下生成需要的目录结构 (2) 利用genromfs工具, 将/cygdrive/d/aaaa/uClinux-44b0ii/romfs目录生成为ROMdisk的romfs映像文件romfs.img genromfs–v–V"ROMdisk"-f/cygdrive/d/aaaa/images/romfs.img –d/cygdrive/d/aaaa/uClinux-44b0ii/romfs
(3) 将romfs.img作为初始化数据连接到Linux内核当中 (4) 使用romfs的文件系统的时候,可以采用mount命令直接将其挂接到合适的目录下,例如(假设/dev/ram0是romfs文件系统的设备): mount -t romfs /dev/rom0 /var
将会把/dev/ram0挂接到/var目录上去,此后直接对/var目录进行操作即可。但是,romfs映射到内存中,它仍旧无法支持动态擦写保存。将会把/dev/ram0挂接到/var目录上去,此后直接对/var目录进行操作即可。但是,romfs映射到内存中,它仍旧无法支持动态擦写保存。 对于系统需要动态保存的数据可以采用虚拟ramdisk或JFFS的方法进行处理。
9.2.2 ramfs文件系统 ramdisk是使用RAM虚拟的磁盘(该驱动程序在/linux/drivers/block/rd.c),是一个内存块,作为一个盘分区使用;或者说将内存模拟为硬盘空间,从而可以像对待硬盘空间一样在其上保存文件。
使用ramdisk主要是为了提高访问速度,若事先知道特定的文件将被高频率访问,通过将文件存放在内存里就可以提高性能。使用ramdisk主要是为了提高访问速度,若事先知道特定的文件将被高频率访问,通过将文件存放在内存里就可以提高性能。 在这个虚拟磁盘的基础上,加载EXT2文件系统来管理和操作文件。
使用ramdisk是非常简单的。 ramdisk的大小是可以配置的,其配置项是/config/.config文件中的CONFIG_USER_RAMIMAGE_RAMFS128(128K)。ramdisk的加载过程包含在/vendors/micetek/44b/rc文件中: bin/expand /etc/ramfs.img /dev/ram0 mount -t ext2 /dev/ram0 /var
首先将预先生成的EXT2的磁盘映像的压缩格式,释放到ram块设备上。首先将预先生成的EXT2的磁盘映像的压缩格式,释放到ram块设备上。 然后使用mount命令将ram块设备中的文件系统安装到根文件系统的/var下。 随后就可以对ramdisk进行文件操作了。
9.2.3 JFFS与JFFS2文件系统 ramdisk是运行在内存中的,所以在系统掉电后,所有保存的数据都会丢失。 这时,一个比较好的选择是JFFS文件系统(最新的版本是JFFS2),JFFS文件系统一般使用FLASH作为磁盘,所以在掉电后数据不会丢失; 而且,JFFS可以对由于在掉电时刻操作导致的不完整数据进行修复。
1.JFFS (1) 存储格式 第一版本的JFFS是一个日志结构的文件系统。在Flash的存储空间中,数据和辅助信息都依次存放于其中。 在该文件系统中,只有一种文件节点,它通过jffs_raw_inode这个结构进行描述。每个这样的节点都关联到某个文件上,其中包含了一个简单的头部、辅助信息以及存储的数据。
其中存储的辅助信息不仅包括通常所记录的文件inode信息(如uid,gid等),也包含了它所关联的文件的名字等。其中存储的辅助信息不仅包括通常所记录的文件inode信息(如uid,gid等),也包含了它所关联的文件的名字等。 由于在JFFS中,大的文件都分为很多节点存放,所以除了必须存放数据之外,还要额外保存这段数据在文件中的偏移量。
设备文件节点和符号链接等特殊的文件只需要存储很少量的文件信息,例如设备文件只需要在数据区存放主次设备号即可,而符号链接文件则只需要在数据区存放链接目标的文件名称即可。设备文件节点和符号链接等特殊的文件只需要存储很少量的文件信息,例如设备文件只需要在数据区存放主次设备号即可,而符号链接文件则只需要在数据区存放链接目标的文件名称即可。 所以这种文件只需要占用很小的空间,通常不会占用超过一个节点。
删除文件的时候,采用的方法是在辅助信息存放的地方设置一个已删除标记,所有关于被删除文件的Flash块都会加上这个已删除标记,在使用该文件的文件句柄释放之后,这些节点就成为废弃节点了。
此外,在更新文件的时候,新的文件存放的节点会添加到所有已经使用的存储空间的末尾,旧版本的文件也会被废弃,等待在回收空间的时候重新分配利用。此外,在更新文件的时候,新的文件存放的节点会添加到所有已经使用的存储空间的末尾,旧版本的文件也会被废弃,等待在回收空间的时候重新分配利用。 第一版本JFFS只有一种记录节点格式,所以尚不支持硬链接。
(2) 文件系统操作的实施过程 ① 挂接 挂接JFFS文件系统时,会把整个存储设备扫描一次,每个存储块都读取一次,然后根据所有节点中存储的信息来生成一个文件系统的目录树,同时也自动生成了一个文件在Flash中物理存储位置的对应表,用来进行文件的寻址操作。
② 读取 文件目录结构可以通过mount时生成的信息获得,cd和rmdir等目录操作都可以直接根据这些信息来确定如何操作。 而读取文件的内容的时候,利用mount时生成的物理地址表可以轻松地将指定的内容读入到缓存区中以备使用。
③ 改变属性 例如改变文件的属主(chown命令)和操作权限(chmod命令)等操作,只需要将一个记录新的信息的节点写到Flash已利用的存储空间的末尾,然后将旧节点标记为废弃节点即可。 写文件等操作也与此类似,并不是通过直接改写旧节点来完成的。
(3) 空间回收 可以看出,在JFFS的操作中,是不会对废弃的存储块来进行重新利用的。随着对文件系统进行过的操作不断积累,占用的存储块会越来越多,已经利用的Flash空间就会不断地增长。 当所有存储块都被占用了之后(可能有一些标记为废弃,但仍然是被占用的),文件系统就要开始对废弃的存储块进行回收再利用了。
当然,回收废弃空间的时候,如果发现所有回收的空间加起来仍不足以满足当前操作的需求,那么系统不能继续当前的操作;当然,回收废弃空间的时候,如果发现所有回收的空间加起来仍不足以满足当前操作的需求,那么系统不能继续当前的操作; 如果是内核线程请求分配空间,那么该线程进入睡眠状态;如果是用户程序请求进行写操作,那么将会返回ENOSPC错误信息。
在进行空间回收时,系统自动从所有存储块中的第一个开始进行分析,不断将废弃的;节点回收,将尚在使用的节点进行合并,这样最终合成出整个的——块废弃的Flash存储块,在进行空间回收时,系统自动从所有存储块中的第一个开始进行分析,不断将废弃的;节点回收,将尚在使用的节点进行合并,这样最终合成出整个的——块废弃的Flash存储块, 这样就可以将这一整块存储块的内容一次性擦除,成为新的空闲块。
(4) 缺陷 关于空间回收,可以看出,JFFS并没有进行太多优化。 它是按照顺序,从第一个数据块开始腾出空间,如果第一块写满了有效数据,它也会将这些数据后移,腾出第一块来作为空闲块。
在极端的情况下,效率会非常低。当然,这种方式也保证了Flash的每一块都可以得到相同的擦写次数,有利于提高整个Flash设备的使用寿命。在极端的情况下,效率会非常低。当然,这种方式也保证了Flash的每一块都可以得到相同的擦写次数,有利于提高整个Flash设备的使用寿命。