您现在的位置:e-works > 智造书屋 > 书籍列表 > Linux安全策略与实例 > Linux文件系统基本原理和概念

第三章 Linux文件系统安全

第一节 Linux文件系统基本原理和概念

    3.1.1 Linux常用的文件系统

    1.常见的文件系统类型

    随着Linux的不断发展,其支持的文件系统也在迅速扩充。特别是Linux 2.4内核正式推出后,出现了大量新的文件系统,其中包括日志文件系统Ext3、ReiserFS、XFS、JFS和其他文件系统。Linux系统核心可以支持十多种文件系统类型,包括JFS、ReiserFS、Ext、Ext2、Ext3、ISO9660、XFS、Minix、MSDOS、UMSDOS、VFAT、NTFS、HPFS、NFS、SMB、SysV、PROC等。其中,较为普遍的有如下几种:

    (1)Minix是Linux支持的第一个文件系统,对用户有很多限制,性能低下,有些没有时间标记,文件名最长14个字符。Minix文件系统最大的缺点是只能使用64MB的硬盘分区,所以目前已经没有人使用该文件系统了。

    (2)Xia是Minix文件系统修正后的版本,在一定程度上解决了文件名和文件系统大小的局限;但没有新的特色,目前很少有人使用。

    (3)ISO9660标准CDROM文件系统,通用的Rock Ridge增强系统,允许长文件名。

    (4)NFS(Network File System)是Sun公司推出的网络文件系统,允许在多台计算机之间共享同一文件系统,易于从所有计算机上存取文件。

    (5)SysV是System V/Coherent在Linux平台上的文件系统。

    (6)扩展文件系统(Ext File System)是随着Linux不断地成熟而引入的,它包含了几个重要的扩展,但提供的性能不令人满意。1994年人们引入了第二扩展文件系统(second Extended Filesystem,Ext2)。

    (7)Ext3(Third Extended Filesystem)是由开源社区开发的日志文件系统,被设计成Ext2的升级版本,尽可能地方便用户从Ext2向Ext3迁移。Ext3在Ext2的基础上加入了记录元数据的日志功能,努力保持向前和向后的兼容性。这个文件系统也许称为Ext2的下一个版本更为合适。Ext3还支持异步的日志,这意味着其性能可能比Ext2还好。

    (8)Ext4(Forth Extended Filesystem)是Linux文件系统的一次革命。在很多方面,Ext4相对于Ext3的进步要远超过Ext3相对于Ext2的进步。

    除了上面这些Linux文件系统外,Linux还可以支持基于Windows和Netware的文件系统,例如UMSDOS、MSDOS、VFAT、HPFS、SMB和NCPFS等。兼容这些文件系统对Linux用户来说也是很重要的,毕竟在桌面环境下Windows文件系统是很流行的,而Netware网络也有许多用户,Linux用户也要共享这些文件系统的数据。

    (9)UMSDOS是一种Linux下的支持MSDOS文件系统的驱动,支持长文件名、所有者、允许权限、连接和设备文件。允许一个普通的MSDOS文件系统用于Linux,而且无须为其建立单独的分区。

    (10)MSDOS是在DOS、Windows和某些OS/2操作系统上使用的一种文件系统,其名称采用“8+3”的形式,即8个字符的文件名加上3个字符的扩展名。

    (11)VFAT是在Windows 9x和Windows 2000下使用的一种DOS文件系统,其在DOS文件系统的基础上增加了对长文件名的支持。

    (12)HPFS称为高性能文件系统(High Performance File System),它是微软LAN Manager中的文件系统,同时也是IBM的LAN Server和OS/2的文件系统。HPFS能访问较大的硬盘驱动器,提供了更多的组织特性,并改善了文件系统的安全特性。

    (13)SMB是一种支持Windows for Workgroups、Windows NT和LAN Manager的基于SMB协议的文件系统。

    (14)NCPFS是Novell NetWare中的使用NCP协议的文件系统。

    (15)NTFS是Windows 2000/XP/2003操作系统支持的特别为网络和磁盘配额、文件加密等安全特性设计的磁盘格式。

    2.Ext4文件系统概览

    Ext4是Linux内核版本2.6.28的重要部分。它是Linux文件系统的一次革命。Ext3相对于Ext2的改进主要在于日志方面,但是Ext4相对于Ext3的改进是更深层次的,是文件系统数据结构方面的优化。一个高效的、优秀的、可靠的和极具特点的文件系统就此诞生。目前,该文件系统并未在所有的Linux发行套件中完全普及使用,还处于初期的测试阶段。其具有如下几方面的特性:

    (1)兼容性:任何Ext3文件系统都可以轻松地迁移到Ext4文件系统,用户只需要在只读模式下运行几条命令即可。这就意味着用户完全可以不格式化硬盘、不重装操作系统、不重装软件环境,就能够顺利地升级到Ext4文件系统。这种升级方法不会损害用户硬盘上的数据和资料,因为Ext4仅会在新的数据上使用,而基本不会改动原有数据。

    (2)更大的文件系统/文件大小:Ext3支持最大16TB(1TB等于1024GB)的文件系统,2TB的文件大小。Ext4将支持最大1EB(1EB等于1024TB)的文件系统,16TB的文件大小。上述这个特性是由于Ext4采用了48位寻址。之所以还未采用64位寻址是因为就目前的开发进展来看,实现64位寻址存在一些技术限制,但是Ext4已经在考虑这个问题了,在不久的将来,Ext4将实现完全的64位支持。

    (3)子目录可扩展性:目前的Ext3中,单个目录下的子目录数目的上限是32000个。而在Ext4中打破了这种限制,可以创建无限多个子目录。

    (4)Extent:传统的类UNIX文件系统,比如Ext3,都是使用一个间接数据块映射表来记录每一个数据块的分配情况的。但是这种机制对于超大文件的存储是有缺陷的,特别是当对超大文件进行删除和截断操作时。映射表会对每一个数据块进行记录,而一个超大文件将占有很多的数据块,因此将造成映射表变得无比臃肿,难以维护。Ext4引入了一个新的概念,叫做Extent。一个Extent是一个地址连续的数据块的集合。比如一个100MB的文件将被分配给一个单独的Extent,这样就不用像Ext3那样新增25600个数据块的记录(一个数据块是4KB)。而超大型文件会被分解在多个extent里。Extent的实现提高了文件系统的性能,减少了文件碎片。

    (5)多块分配:在Ext3中,“将新的数据写入磁盘的哪些空闲块”是由块分配器来控制的。但是Ext3的块分配器存在一定缺陷,那就是它一次只能分配一个数据块(4KB),这就意味着,如果系统需要向磁盘中写入100MB的数据,就需要调用块分配器25 600次,而且由于块分配器无法获知总的分配块数,所以也无法对分配空间和分配位置进行优化。在Ext4中,使用了“多块分配器”,即一次调用可以分配多个数据块,这种机制提高了系统的性能,而且使得分配器有了充足的优化空间。

    (6)延迟分配:延迟分配(Delayed allocation)是一项少数现代文件系统才具有的优秀特性,比如XFS、ZFS、btrfs(better FS)以及Reiser4。它能够尽可能地积累更多的数据块再分配出去,而传统的文件系统则会尽快将数据块分配出去,如Ext3,Reiser3等。这项特性与Extents特性以及多块分配特性结合,会使磁盘I/O性能得到显著提高。

    (7)更快速的fsck:在Ext3中,fsck本身是个速度很慢的操作,因为它要检查文件系统里的每一个i结点。但是,Ext4会维护一个未使用的i结点表,在进行fsck操作时,会跳过表中结点,只检查正在使用的i结点。这种机制使fsck的效率提高为Ext3文件系统的2~20倍。不过要注意,这个未使用的i结点表是由fsck来维护的,而不是由Ext4,因此用户必须首先运行一次fsck来生成。这样,在下次再运行fsck时才可以享受提速(虽然表是由fsck来维护的,但用户还是需要从Ext3升级到Ext4才能够享受这项功能)。

    (8)日志校验:日志要算是磁盘中最常用的部分了,也是最容易使硬盘出问题的机制之一。如果用户不幸使用一个已经崩溃的日志来恢复系统的话,将导致更大规模的系统崩溃。Ext4提供校验日志数据的功能,可以查看其潜在错误。而且,Ext4还会将Ext3日志机制中的“两阶段提交”动作合并为一个步骤,这种改进将使文件系统的操作性能提升20%。这就是Ext4在日志机制方面对可靠度和性能的双重提升。

    (9)在线磁盘整理:这个特性没有包括在内核版本2.6.28之中,但是它很有可能会在下一个版本中引入。虽然Extents、多块分配和延迟分配都有助于减少磁盘碎片,但是磁盘碎片仍然会产生。举例来说:用户在一个目录下建立了三个文件f1,f2,f3,它们被按序写入到连续的一段硬盘空间中。然而几天之后,用户想要更新文件f2,也就是位于这段连续空间的中间那一段的那个文件。要向这个文件中增加一些字符。很明显,在这段连续空间之中已经没有地方放下增加的这些字符,此时只能将这个f2文件移动到一个新的连续空间之中。这导致了f2文件和f1、f3文件离得非常远,读取也相对缓慢了。这就产生了磁盘碎片。还有,可引导文件应该被放在连续的硬盘空间中,但是磁盘整理机制并不知道哪些文件是可引导文件。为了解决上述问题,Ext4将支持在线磁盘整理,e4defrag工具也具备更智能的磁盘碎片整理功能。

    (10)更大的i结点:Ext3支持自定义i结点大小,但是默认的i结点大小是128B,Ext4将默认大小提升到256B。增加的空间用来存储更多的结点信息,这样有利于提升磁盘性能。

    (11)i结点预留机制:当新建一个目录时,若干i结点会被预留下来,等新的文件在此目录中创建时,这些预留的i结点就可以立即被使用。文件的建立和删除将变得更加高效。

    (12)纳秒级的时间戳:在Ext3中,时间精度是秒。在Ext4中,时间精度提升到了纳秒。

    (13)可持续预分配:这个特性已经出现在Ext3的最后几个内核版本中,并且也可以由glibc在不支持此功能的文件系统中模拟产生,允许应用程序去预分配磁盘空间。应用程序告知文件系统给预留出一定的空间,文件系统会据此预分配必要的数据块,但是这些数据块将会是空的,直到应用程序向里面写入数据为止。这种机制会常常在P2P应用程序中用到,因为P2P应用程序下载文件常常需要几天的时间。这种机制也防止了磁盘碎片的产生,因为文件系统会一次性分配尽可能连续的数据块给应用程序。再者,这种机制对于实时系统非常重要,因为一旦没有这种机制,可能导致在一次重要操作的半途中遇到磁盘空间已满的情况。这项特性是通过调用posix_fallocate()来实现的。

    3.1.2 Linux文件

    本节详细介绍Linux文件系统中文件的定义、文件名的规定以及文件的类型。

    1.文件与文件名

    在多数操作系统中都有文件的概念。在Linux中文件是存储信息的基本结构,是被命名(称为文件名)的存储在某种介质(如磁盘、光盘和磁带等)上的一组信息的集合。Linux文件均为无结构的字符流形式。文件名是文件的标识,由字母、数字、下划线和圆点组成的字符串来构成。用户应该尽量选择有意义的文件名,以方便识别和记忆。值得注意的是:Linux要求文件名的长度限制在255个字符以内。

    为了便于管理和识别,用户可以把扩展名作为文件名的一部分。圆点用于区分文件名和扩展名。扩展名对文件分类是十分有用的。用户可能对某些大众已接纳的标准扩展名比较熟悉。例如,用C++语言编写的源代码文件总是具有cpp的扩展名。用户可以根据自己的需要,随意加入自己的文件扩展名。以下例子给出一些有效的Linux文件名:

    //不带扩展名的文件

    HelloLinux

    //文本文件

    Squid.conf

    //perl脚本文件

    Install.pl

    //C程序源文件

    Test.c

    2.文件的类型

    Linux系统中有五种基本的文件类型:普通文件、目录文件、设备文件、链接文件和管道文件。

    (1)普通文件:是用户最经常使用和熟悉的文件,它又分为文本文件和二进制文件两种。

    文本文件:这类文件以文本的ASCII码形式存储在计算机中,是以“行”为基本结构的一种信息组织和存储方式。

    二进制文件:这类文件以文本的二进制形式存储在计算机中。用户一般不能直接读懂它们,只有通过相应的软件才能将其显示出来。二进制文件一般是可执行程序、图形、图像、声音等。

    (2)目录文件:主要目的是用于管理和组织系统中的大量文件,其存储一组相关文件的位置、大小等与文件有关的信息。目录文件一般简称为目录。

    (3)设备文件:Linux系统把每一个I/O设备都看成一个文件(这点与Windows系列操作系统有很大区别),与普通文件一样处理,这样可以使文件与设备的操作尽可能统一。从用户的角度来看,对I/O设备的使用和一般文件的使用一样,不必了解I/O设备的细节。设备文件可以细分为块设备文件和字符设备文件。前者的存取是以字符块为单位的,后者则以单个字符为单位。

    (4)链接文件:链接文件是一种特殊的文件,实际上是指向一个真实存在的文件的链接,类似于Windows下的快捷方式。根据链接文件的不同,它又可以细分为硬链接文件和符号链接文件。

    (5)管道文件:管道文件是一种很特殊的文件,主要用于不同进程间的信息传递。当两个进程间需要进行数据或信息传递时,可以通过管道文件。一个进程将需传递的数据或信息写入管道的一端,另一进程则从管道的另一端取得所需的数据或信息。管道通常建立在调整缓存中。

    3.1.3 Linux目录

    本节详细介绍Linux系统中树型目录结构、工作目录、用户主目录等重要概念。

    1.树型目录结构

    在计算机系统中存有大量的文件,如何有效地组织与管理它们,并为用户提供一个使用方便的接口是文件系统的主要任务。Linux系统以文件目录的方式来组织和管理系统中的所有文件。所谓文件目录就是将所有文件的说明信息采用树型结构组织起来。整个文件系统有一个“根”(root),然后在根上分“杈”(directory),任何一个分杈上都可以再分杈,杈上也可以长出“叶子”。“根”和“杈”在Linux中称为“目录”或“文件夹”。而“叶子”则是文件。实践证明,这种结构的文件系统效率高,现代操作系统基本上都采用这种结构方式。

    如前所述,目录也是一种类型的文件。Linux系统通过目录将系统中所有的文件分级、分层组织在一起,形成了Linux文件系统的树型层次结构。以根目录为起点,所有其他的目录都由根目录派生而来,用户可以浏览整个系统,可以进入任何一个已授权进入的目录,从而访问其中的文件。

    实际上,各个目录结点之下都会有一些文件和子目录。并且,系统在建立每一个目录时,都会自动为它设定两个目录文件,一个是“.”,代表该目录自己;另一个则是“..”,代表该目录的父目录。特殊的是,对于根目录,“.”和“..”都代表其自身。

    Linux目录提供了管理文件的一个方便途径。每个目录中都可以包含文件。用户可以为自己的文件创建自己的目录,也可以把一个目录下的文件移动或复制到另一个目录下,而且能移动整个目录,与系统中的其他用户共享目录和文件。也就是说,用户能够方便地从一个目录切换到另一个目录,而且可以设置目录和文件的管理权限,以便允许或拒绝其他人对其进行访问。同时,文件目录结构的相互关联性使分享数据变得十分容易,几个用户可以访问同一个文件,因此允许用户设置文件的共享程度。根目录(系统目录)是Linux系统中的特殊目录。Linux是一个多用户系统,操作系统本身的驻留程序存放在以根目录开始的专用目录中。

    2.工作目录与用户主目录和路径

    从逻辑上讲,用户登录Linux系统之后,每时每刻都处在某个目录之中,此目录被称作工作目录或当前目录(Working Directory)。工作目录是可以随时改变的。用户初始登录到系统中时,其主目录(Home Directory)就成为其工作目录。工作目录用“.”表示,其父目录用“..”表示。

    用户主目录是系统管理员增加用户时建立的(以后也可以根据实际情况改变),每个用户都有自己的主目录,不同用户的主目录一般不相同。用户刚登录到系统中时,其工作目录便是该用户的主目录,通常与用户的登录名相同。用户可以通过一个“~”符来引用自己的主目录。

    举个例子,假设用户liyang的主目录为/home/liyang,那么如下两条命令中所采用的两条路径就是完全一样的,因而其运行结果是相同的:

    #cat ~/own/softwares

    #cat /home/liyang/own/softwares

    3.路径

    对文件进行访问时,要用到“路径”的概念。顾名思义,路径是指从树型目录中的某个目录层次到某个文件的一条道路。此路径的主要构成是目录名称,中间用“/”隔开。任一文件在文件系统中的位置都是由相应的路径决定的。

    用户在对文件进行访问时,要给出文件所在的路径。路径又分相对路径和绝对路径两种。绝对路径是指从“根”开始的路径,也称为完全路径;相对路径是从用户工作目录开始的路径。特别需要注意,在树型目录结构中到某一确定文件的绝对路径和相对路径均只有一条。绝对路径是确定不变的,而相对路径则随着用户工作目录的变化而变化。

    用户要访问一个文件时,可以通过路径名来引用。并且为操作方便起见,完全可以根据要访问的文件与用户工作目录的相对位置来引用它,而不必列出这个文件完整的路径名。例如,用户liyang有一个名为program的目录,该目录中有两个文件:time.conf和test.java。若用户liyang想显示出其program目录中的名为time.conf的文件,可以使用下列以绝对路径为基准的命令:

    //使用绝对路径访问

    #cat /home/liyang/program/time.conf

    同样,如果用户已经切换到其主目录,那么此时也可以根据文件time.conf与当前工作目录的相对位置来引用该文件。这时命令为:

    //切换到用户主目录

    #cd /home/liyang 

    //使用相对路径访问

    #cat program/time.conf

    3.1.4 Linux目录结构

    Linux系统的目录层次结构比较复杂,下面对其进行介绍。

    (1)/:根目录。在Windows,DOS或者其他类似的操作系统里面,每个分区都会有一个相应的根目录。但是Linux和其他UNIX系统则把所有的文件都放在一个目录树里面,/就是唯一的根目录。一般来讲,根目录下面很少保存什么文件,或者只有一个内核映像。

    (2)/boot:很多Linux系统把内核映像和其他一些和启动有关的文件都放在这里。

    (3)/tmp:一般只有启动时产生的临时文件才会放在这个地方。用户自己的临时文件都放在/var/tmp。

    (4)/mnt:这个目录下面放着一些用来安装其他设备的子目录,比如说/mnt/cdrom或者/mnt/floppy。在有些Linux中这个目录是被/mount或/media代替的。

    (5)/lib:启动的时候所要用到的库文件都放在这个目录下。那些非启动用的库文件都会放在/usr/lib下。内核模块是被放在/lib/modules/(内核版本)下的。

    (6)/proc:这个目录在磁盘上其实是不存在的,只存在于内存中。里面的文件都是关于当前系统的状态,包括正在运行的进程、硬件状态、内存使用的多少等。系统关闭时即消失。

    (7)/dev:这个目录下保存着所有的设备文件。里面有一些由Linux内核创建的用来控制硬件设备的特殊文件。

    (8)/var:这里有一些被系统改变过的数据。比如说/var/tmp,就是用来储存临时文件的。还有很多其他的进程和模块把它们的记录文件也放在这个地方,包括如下一些重要的子目录:

    /var/log:这里放着绝大部分的记录文件。随着时间的增长,这个目录会变得很庞大,所以要定期清理。

    /var/run:包括了各种运行时的信息。

    /var/lib:包括了一些系统运行时需要的文件。

    /var/spool:邮件、新闻、打印序列的所在地。

    (9)/root:root用户的主目录。

    (10)/home:一般用户的主目录都会放在这个目录下。在Linux下,可以通过#cd ~ 来进入自己的主目录。

    (11)/etc:这里保存着绝大部分的系统配置文件。相对来讲,单个用户的系统配置文件会保存在这个用户自己的主目录里面。下面列举其中一些重要的子目录:

    /etc/X11:这里放着X窗口系统(Linux中的图形用户界面系统)所需要的配置文件。XF86Config就是把配置储存到这个地方的。/etc/X11/fonts里面放着一些服务器需要的字体,还存放一些窗口管理器的配置文件。

    /etc/init.d:这个目录保存着启动描述文件,包括各种模块和服务的加载描述。所以如果不清楚的话,千万不要随便删除其中的文件,这里存放的文件都是系统自动进行配置的,不需要用户配置。

    /etc/rcS.d:这里放着一些链接到/etc/init.d的文件,根据runlevel的不同,执行相应的描述。这里的文件名都是由S来开头的,然后是一个两位的数字——表示各种服务启动的顺序。比如,S24foo就是在S42bar前面执行的。接着就是相应的链接到/etc/init.d下面的文件的名字了。

    /etc/rc0.d - /etc/rc6.d:这里面也是一些链接文件,和/etc/rcS.d差不多。不同的是,这些文件只会在指定的runlevel下运行相应的描述。0表示关机,6表示重启。所有以K开头的文件表示关闭,所有以S开头的文件表示重启。目前来讲,文件的命名方式和/etc/rcS.d是一样的。

    (12)/bin,/sbin:这里分别放着启动时所需要的普通程序和系统程序。很多程序在启动以后也很有用,它们放在这个目录下是因为它们经常被其他程序调用。

    (13)/usr:这是一个很复杂、庞大的目录。除了上述目录之外,几乎所有的文件都存放在这下面。下面列举其中一些重要的子目录:

    /usr/X11R6,/usr/X11,/usr/Xfree86:这里保存着X窗口系统所需要的文件,它的目录结构和/usr是一样的。

    /usr/bin:二进制可执行文件存放的目录,这里放着绝大部分应用程序。

    /usr/sbin:这里放着绝大部分系统程序。

    /usr/games:游戏程序和相应的数据会放在这里。

    /usr/include:这个目录保存着C和C++的头文件。

    /usr/lib:启动时用不到的库文件都会放在这里。

    /usr/info:这里保存着GNU Info程序所需要的数据。

    /usr/man:这里保存着man程序所需要的数据。

    /usr/src:这里保存着源代码文件。

    /usr/doc:这里保存着各种文档文件。这些文件可以帮助用户了解Linux、解决问题并掌握一些技巧。

    /usr/local:这里保存着本地计算机所需要的文件。在用户进行远程访问的时候特别有意义。这个目录在有些Linux系统下就是一个单独的分区,存放一些这台机子所属的那个用户的文件。里面的结构和/usr是一样的。

    /usr/share:这里保存着各种共享文件。