linux 文件系统详解

 

From:http://soysauce93.blog.51cto.com/7589461/1715655

From:http://blog.csdn.net/new0801/article/details/63687127

Linux 的虚拟文件系统(强烈推荐):http://blog.csdn.net/heikefangxian23/article/details/51579971

鸟哥 Linux 磁盘与文件系统管理http://linux.vbird.org/linux_basic/0230filesystem.php

 

 

一、硬盘物理结构及相关概念

 

硬盘内部视角实物图

硬盘内部视角逻辑图

扇区、磁道、柱面图 

  1. 磁头(head)数:每个盘片一般有上下两面,分别对应1个磁头,共2个磁头,实现数据的存取
  2. 磁道(track):当磁盘旋转时,磁头若保持在一个位置上,则每个磁头都会在磁盘表面划出一个圆形轨迹,这些圆形轨迹就叫做磁道,从外边缘的0开始编号,根据磁化方向来存数数据0和1
  3. 柱面(cylinder):不同盘片的相同编号的磁道构成的圆柱面就被称之为柱面,磁盘的柱面数与一个盘面上的磁道数是相等的
  4. 扇区(sector):每个磁道都别切分成很多扇形区域,每个磁道的扇区数量相同,每个扇区大小为512字节
  5. 圆盘(platter):就是硬盘的盘片,为实现大容量,一般都是多个

硬盘的容量=柱面数×磁头数×扇区数×512(字节数)

 

 

二、硬盘逻辑结构及相关概念

 

整体逻辑结构图

MBR(Master Boot Record)

硬盘的0柱面、0磁头、1扇区称为主引导扇区(也叫主引导记录MBR)。它由三个部分组成:硬盘主引导程序(BootLoader)、硬盘分区表DPT(Disk Partition table)和魔数(Magic Number)。

  1. Boot Loader:主引导程序,启动操作系统的一段代码,占446个字节
  2. DPT:占64个字节,硬盘中分区有多少以及每一分区的大小都记在其中
  3. Magic Number:占2个字节,固定为0xAA55或0x55AA,这取决于处理器类型,如果是小端模式处理器(如Intel系列),则该值为0xAA55;如果是大端模式处理器(如Motorola6800),则该值为0x55AA

 

主分区、扩展分区、逻辑分区示意图

①:主分区+扩展分区<=4

②:扩展分区最多只有一个

③:要么是三主一扩展,要么是四个主分区,那么剩余未分区的空间将无法使用

 

 

三、Ext2文件系统逻辑结构

 

一个分区最开始处是Boot Sector,然后就是多个块组每个块组又可以细分为如下组成部分:

  • Super Block:记录此 filesystem 的整体信息,包括inode/block的总量、使用量、剩余量, 以及文件系统的格式与相关信息等;由于super block很重要 ,在每个 block group都会存一份进行备份.
  • GDT:Group Descriptor Table,块组描述符,由很多块组描述符组成,整个分区分成多少个块组就对应有多少个块组描述符。每个块组描述符(Group Descriptor)存储一个块组的描述信息,例如在这个块组中从哪里开始是inode表,从哪里开始是数据块,空闲的inode和数据块还有多少个等等。和超级块类似,块组描述符表在每个块组的开头也都有一份拷贝
  • Block Bitmap:块位图就是用来描述整个块组中哪些块已用哪些块空闲的,它本身占一个块,其中的每个bit代表本块组中的一个块,这个bit为1表示该块已用,这个bit为0表示该块空闲可用
  • inode Bitmap:和块位图类似,本身占一个块,其中每个bit表示一个inode是否空闲可用
  • inode Table:一个文件除了数据需要存储之外,一些描述信息也需要存储,例如文件类型(常规、目录、符号链接等),权限,文件大小,创建/修改/访问时间等,也就是ls-l命令看到的那些信息,这些信息存在inode中而不是数据块中,每个文件都有一个inode,一个块组中的所有inode组成了inode表,inode表占多少个块在格式化时就要决定并写入块组描述符中
  • Data Blocks:对于常规文件,文件的数据存储在数据块中,对于目录,该目录下的所有文件名和目录名存储在数据块中,文件名保存在它所在目录的数据块中,除文件名之外,ls -l命令看到的其它信息都保存在该文件的inode中,目录也是一种文件,是一种特殊类型的文件,对于符号链接,如果目标路径名较短则直接保存在inode中以便更快地查找,如果目标路径名较长则分配一个数据块来保存设备文件、FIFO和socket等特殊文件没有数据块,设备文件的主设备号和次设备号保存在inode中

目录文件

注:
    ① 其实文件名和文件类型都是在目录中存放,而文件的其他元数据信息则是在Inode中存放
    ② 文件系统各分区之间物理视角上是并行的,逻辑视角上必须得有上下级关系,所有的文件都必须直接或间接从根开始

 

 

四、读取、创建、删除、复制、剪切过程

 

1、读取文件

例如:/etc/httpd/httpd.conf

首先根是自引用的,也就是根的Inode号是已知的,再根据Inode Table可以知道根的Inode号对应的Block号,然后找到对应的block,block里面有个目录项,也即Dentry,每个目录项记录了根下所有直接子目录的Inode与文件名的对应关系(也包括文件类型等),例如var对应的Inode号为2883585,etc对应的Inode号为1507329等等,此时找到etc文件对应的Inode号,再通过查找Inode Table可以得知etc文件对应的Block,再通过读取Block里面的Dentry可以得知httpd文件对应的Inode,再查找Inode Table可以查到httpd文件对应的Block,再在对应的Block里面查询Dentry可以得知httpd.conf文件对应的Inode号,再次查询Inode Table可以找到对应的Block,于是数据就可以读取了

 

2、创建文件

例如:/etc/testfile.txt

想要创建一个文件,首先得先给这个文件分配Inode和Block。首先扫描Inode Bitmap查找空闲Inode,再去Inode Table中写入想要创建文件的元数据,例如权限、属主属组、大小、时间戳、以及这个Inode对应所占据的Block。然后再找到根的Inode,找到根对应的Block,里面Dentry记录了etc及其对应的Inode,再通过Inode Table找到etc文件对应的Block,于是在Dentry里面添加一条记录,testfile.txt与其对应的Inode号,文件类型等信息。到此一个文件便创建了。

 

3、删除文件

例如:/etc/fstab

删除文件直接上级目录(etc)里面的那条Dentry记录,Inode Bitmap里面把文件(fstab)原先对应的Inode号标记为未使用,Block Bitmap中把文件(fstab)原先对应的Block标记为未使用。删除文件本身并没有删除文件所对应的Block和Inode,也就是说Block上的数据并没有被抹除,除非后面向其Block中覆盖数据

 

4、复制文件

复制文件本质就是新建一个文件,并填充源文件数据的过程,详细可参考上面的创建和读取文件过程

 

5、剪切文件

在同一个分区下,剪切速度非常快,这是因为其本质也只是将Dentry记录换一个目录而已,所以根本就不涉及什么耗时的操作。而跨分区剪切文件的过程其实就是在另外一个分区上创建一个新文件,并复制,复制完成之后再删除原先分区上数据的一个过程。

 

 

五、软连接硬链接 

 

软连接(符号链接)硬链接

  • 软连接本质:在Inode Table中本该存储Block号信息的地方存储了一个路径,如:/etc/httpd/httpd.conf,所以软连接文件的大小都是其对应的文件路径的字符个数
  • 硬链接本质:Inode号相同的文件彼此都可称为硬链接,只是再另外一个目录中添加的Dentry记录为同一个Inode而已
ln - make links between files    # 给文件创建链接
 
SYNOPSIS
       ln [-s -v] SRC DEST
        -s:创建软链接
        -v:显示创建详细过程
        
[root@soysauce test]# ll /etc/rc.sysinit             # 权限为777,并且大小为所指向的字符个数
lrwxrwxrwx. 1 root root 15 Aug 28 10:32 /etc/rc.sysinit -> rc.d/rc.sysinit
[root@soysauce test]# ln -s inittab inittab_soft        # 创建软连接
[root@soysauce test]# ln  inittab inittab_hard         # 创建硬链接
[root@soysauce test]# ll -i
total 8
265301 -rw-r--r-- 2 root root 884 Nov 23 13:25 inittab    
265301 -rw-r--r-- 2 root root 884 Nov 23 13:25 inittab_hard     # 硬链接inode号与源文件相同
265310 lrwxrwxrwx 1 root root   7 Nov 23 13:55 inittab_soft -> inittab
[root@soysauce test]# ll -i
total 8
265301 -rw-r--r-- 2 root root 884 Nov 23 13:25 inittab        # 此时硬链接次数都为2
265301 -rw-r--r-- 2 root root 884 Nov 23 13:25 inittab_hard
265310 lrwxrwxrwx 1 root root   7 Nov 23 13:55 inittab_soft -> inittab
[root@soysauce test]# rm -f inittab                           # 删除源文件
[root@soysauce test]# ll -i
total 4
265301 -rw-r--r-- 1 root root 884 Nov 23 13:25 inittab_hard    # 此时硬链接次数变为了1
265310 lrwxrwxrwx 1 root root   7 Nov 23 13:55 inittab_soft -> inittab    # 此时软连接也一直在闪烁
[root@soysauce test]# head -3 inittab_hard                 # 因为篇幅原因,顾只查看3行
# inittab is only used by upstart for the default runlevel.
#
# ADDING OTHER CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.

软连接(符号链接)与硬链接区别

  • 硬链接
            ①只能对文件创建,不能应用于目录
            ②不能跨文件系统
            ③创建硬链接会增加文件被链接的次数
            ④硬链接次数为1时,再删除就是彻底删除了
            ⑤删除源文件不会影响链接文件
  • 软链接:
            ①可应用于目录
            ②可以跨文件系统
            ③不会增加被链接文件的链接次数
            ④其大小为指定的路径所包含的字符个数
            ⑤删除源文件会影响链接文件

硬链接与复制的区别

互为硬链接的两文件inode号肯定是相同的,对应的block号也是相同的;而复制的文件inode号和block号也肯定不相同,只是block里面存储的数据是一样而已

 

 

六、虚拟文件系统

 

引言

 

Linux 中允许众多不同的文件系统共存,如 ext2、ext3、vfat 等。通过使用同一套文件 I/O 系统 调用即可对 Linux 中的任意文件进行操作而无需考虑其所在的具体文件系统格式;更进一步,对文件的 操作可以跨文件系统而执行。如图 1 所示,我们可以使用 cp 命令从 vfat 文件系统格式的硬盘拷贝数据到 ext3 文件系统格式的硬盘;而这样的操作涉及到两个不同的文件系统。

图片示例_跨文件系统的文件操作

一切皆是文件 " 是 Unix/Linux 的基本哲学之一。不仅普通的文件,目录、字符设备、块设备、 套接字等在 Unix/Linux 中都是以文件被对待;它们虽然类型不同,但是对其提供的却是同一套操作界面。

图片示例_一切皆是文件

而虚拟文件系统正是实现上述两点 Linux 特性的关键所在。

虚拟文件系统( Virtual File System 简称 VFS ), 是 Linux 内核中的一个软件层,用于给用户空间的程序提供文件系统接口;同时,它也提供了内核中的一个 抽象功能,允许不同的文件系统共存。系统中所有的文件系统不但依赖 VFS 共存,而且也依靠 VFS 协同工作。

为了能够支持各种实际文件系统,VFS 定义了所有文件系统都支持的基本的、概念上的接口和数据 结构;同时实际文件系统也提供 VFS 所期望的抽象接口和数据结构,将自身的诸如文件、目录等概念在形式 上与VFS的定义保持一致。换句话说,一个实际的文件系统想要被 Linux 支持,就必须提供一个符合VFS标准 的接口,才能与 VFS 协同工作。实际文件系统在统一的接口和数据结构下隐藏了具体的实现细节,所以在VFS 层和内核的其他部分看来,所有文件系统都是相同的。图3显示了VFS在内核中与实际的文件系统的协同关系。

图片示例_VFS在内核中与其他的内核模块的协同关系

 

我们已经知道,正是由于在内核中引入了VFS,跨文件系统的文件操作才能实现,"一切皆是文件" 的口号才能承诺。而为什么引入了VFS,就能实现这两个特性呢?在接下来,我们将以这样的一个思路来切入 文章的正题:我们将先简要介绍下用以描述VFS模型的一些数据结构,总结出这些数据结构相互间的关系;然后 选择两个具有代表性的文件I/O操作sys_open()和sys_read()来详细说明内核是如何借助VFS和具体的文件系统打 交道以实现跨文件系统的文件操作和承诺“一切皆是文件”的口号。

虚拟文件系统又称虚拟文件系统转换(Virual Filesystem Switch ,简称VFS)。说它虚拟,是因为它所有的数据结构都是在运行以后才建立,并在卸载时删除,而在磁盘上并没有存储这些数据结构,显然如果只有VFS,系统是无法工作的,因为它的这些数据结构不能凭空而来,只有与实际的文件系统,如Ext2、Minix、MSDOS、VFAT等相结合,才能开始工作,所以VFS并不是一个真正的文件系统。与VFS相对,我们称Ext2、Minix、MSDOS等为具体文件系统。

VFS与内核其它子系统之间关系

VFS提供一个统一的接口(实际上就是file_operatoin数据结构),一个具体文件系统要想被Linux支持,就必须按照这个接口编写自己的操作函数,而将自己的细节对内核其它子系统隐藏起来。因而,对内核其它子系统以及运行在操作系统之上的用户程序而言,所有的文件系统都是一样的。实际上,要支持一个新的文件系统,主要任务就是编写这些接口函数。

概括说来,VFS主要有以下几个作用:

  1. 对具体文件系统的数据结构进行抽象,以一种统一的数据结构进行管理。
  2. 接受用户层的系统调用 ,例如write、open、stat、link等等。
  3. 支持多种具体文件系统之间相互访问。
  4. 接受内核其他子系统的操作请求,特别是内存管理子系统

注:以上内容都是摘自深入分析Linux内核源码第8章第一节VFS概述

 

 

VFS数据结构

 

一些基本概念

从本质上讲,文件系统是特殊的数据分层存储结构,它包含文件、目录和相关的控制信息。为了描述 这个结构,Linux引入了一些基本概念:

  • 文件:一组在逻辑上具有完整意义的信息项的系列。在Linux中,除了普通文件,其他诸如目录、设备、套接字等 也以文件被对待。总之,“一切皆文件”。
  • 目录:目录好比一个文件夹,用来容纳相关文件。因为目录可以包含子目录,所以目录是可以层层嵌套,形成文件路径。在Linux中,目录也是以一种特殊文件被对待的,所以用于文件的操作同样也可以用在目录上。
  • 目录项:在一个文件路径中,路径中的每一部分都被称为目录项;如路径/home/source/helloworld.c中,目录 /, home, source和文件 helloworld.c都是一个目录项。
  • 索引节点:用于存储文件的元数据的一个数据结构。文件的元数据,也就是文件的相关信息,和文件本身是两个不同 的概念。它包含的是诸如文件的大小、拥有者、创建时间、磁盘位置等和文件相关的信息。
  • 超级块:用于存储文件系统的控制信息的数据结构。描述文件系统的状态、文件系统类型、大小、区块数、索引节 点数等,存放于磁盘的特定扇区中。

如上的几个概念在磁盘中的位置关系如图所示。

图片示例_磁盘与文件系统.jpg

 关于文件系统的三个易混淆的概念:

  • 创建:以某种方式格式化磁盘的过程就是在其之上建立一个文件系统的过程。创建文现系统时,会在磁盘的特定位置写入 关于该文件系统的控制信息。
  • 注册:向内核报到,声明自己能被内核支持。一般在编译内核的时侯注册;也可以加载模块的方式手动注册。注册过程实 际上是将表示各实际文件系统的数据结构struct file_system_type 实例化。
  • 安装:也就是我们熟悉的mount操作,将文件系统加入到Linux的根文件系统的目录树结构上;这样文件系统才能被访问。

 

VFS 数据结构

VFS 依靠四个主要的数据结构和一些辅助的数据结构来描述其结构信息,这些数据结构表现得就像是对象; 每个主要对象中都包含由操作函数表构成的操作对象,这些操作对象描述了内核针对这几个主要的对象可以进行的操作。

 

超级块对象

存储一个已安装的文件系统的控制信息,代表一个已安装的文件系统;每次一个实际的文件系统被安装时, 内核会从磁盘的特定位置读取一些控制信息来填充内存中的超级块对象。一个安装实例和一个超级块对象一一对应。 超级块通过其结构中的一个域s_type记录它所属的文件系统类型。

根据第三部分追踪源代码的需要,以下是对该超级块结构的部分相关成员域的描述,(如下同):

超级块

struct super_block { //超级块数据结构
        struct list_head s_list;                /*指向超级块链表的指针*/
        ……
        struct file_system_type  *s_type;       /*文件系统类型*/
       struct super_operations  *s_op;         /*超级块方法*/
        ……
        struct list_head         s_instances;   /*该类型文件系统*/
        ……
};

struct super_operations { //超级块方法
        ……
        //该函数在给定的超级块下创建并初始化一个新的索引节点对象
        struct inode *(*alloc_inode)(struct super_block *sb);
       ……
        //该函数从磁盘上读取索引节点,并动态填充内存中对应的索引节点对象的剩余部分
        void (*read_inode) (struct inode *);
       ……
};

 

索引节点对象

索引节点对象存储了文件的相关信息,代表了存储设备上的一个实际的物理文件。当一个 文件首次被访问时,内核会在内存中组装相应的索引节点对象,以便向内核提供对一个文件进行操 作时所必需的全部信息;这些信息一部分存储在磁盘特定位置,另外一部分是在加载时动态填充的。

索引节点

struct inode {//索引节点结构
      ……
      struct inode_operations  *i_op;     /*索引节点操作表*/
     struct file_operations   *i_fop;  /*该索引节点对应文件的文件操作集*/
     struct super_block       *i_sb;     /*相关的超级块*/
     ……
};

struct inode_operations { //索引节点方法
     ……
     //该函数为dentry对象所对应的文件创建一个新的索引节点,主要是由open()系统调用来调用
     int (*create) (struct inode *,struct dentry *,int, struct nameidata *);

     //在特定目录中寻找dentry对象所对应的索引节点
     struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
     ……
};

 

目录项对象

引入目录项的概念主要是出于方便查找文件的目的。一个路径的各个组成部分,不管是目录还是 普通的文件,都是一个目录项对象。如,在路径/home/source/test.c中,目录 /, home, source和文件 test.c都对应一个目录项对象。不同于前面的两个对象,目录项对象没有对应的磁盘数据结构,VFS在遍 历路径名的过程中现场将它们逐个地解析成目录项对象。

目录项

struct dentry {//目录项结构
     ……
     struct inode *d_inode;           /*相关的索引节点*/
    struct dentry *d_parent;         /*父目录的目录项对象*/
    struct qstr d_name;              /*目录项的名字*/
    ……
     struct list_head d_subdirs;      /*子目录*/
    ……
     struct dentry_operations *d_op;  /*目录项操作表*/
    struct super_block *d_sb;        /*文件超级块*/
    ……
};

struct dentry_operations {
    //判断目录项是否有效;
    int (*d_revalidate)(struct dentry *, struct nameidata *);
    //为目录项生成散列值;
    int (*d_hash) (struct dentry *, struct qstr *);
    ……
};

 

文件对象

文件对象是已打开的文件在内存中的表示,主要用于建立进程和磁盘上的文件的对应关系。它由sys_open() 现场创建,由sys_close()销毁。文件对象和物理文件的关系有点像进程和程序的关系一样。当我们站在用户空间来看 待VFS,我们像是只需与文件对象打交道,而无须关心超级块,索引节点或目录项。因为多个进程可以同时打开和操作 同一个文件,所以同一个文件也可能存在多个对应的文件对象。文件对象仅仅在进程观点上代表已经打开的文件,它 反过来指向目录项对象(反过来指向索引节点)。一个文件对应的文件对象可能不是惟一的,但是其对应的索引节点和 目录项对象无疑是惟一的。

文件对象

struct file {
    ……
     struct list_head        f_list;        /*文件对象链表*/
    struct dentry          *f_dentry;       /*相关目录项对象*/
    struct vfsmount        *f_vfsmnt;       /*相关的安装文件系统*/
    struct file_operations *f_op;           /*文件操作表*/
    ……
};

struct file_operations {
    ……
    //文件读操作
    ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
    ……
    //文件写操作
    ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
    ……
    int (*readdir) (struct file *, void *, filldir_t);
    ……
    //文件打开操作
    int (*open) (struct inode *, struct file *);
    ……
};

 

其他VFS对象

和文件系统相关

根据文件系统所在的物理介质和数据在物理介质上的组织方式来区分不同的文件系统类型的。 file_system_type结构用于描述具体的文件系统的类型信息。被Linux支持的文件系统,都有且仅有一 个file_system_type结构而不管它有零个或多个实例被安装到系统中。

而与此对应的是每当一个文件系统被实际安装,就有一个vfsmount结构体被创建,这个结构体对应一个安装点。

和文件系统相关

struct file_system_type {
        const char *name;                /*文件系统的名字*/
        struct subsystem subsys;         /*sysfs子系统对象*/
        int fs_flags;                    /*文件系统类型标志*/

        /*在文件系统被安装时,从磁盘中读取超级块,在内存中组装超级块对象*/
        struct super_block *(*get_sb) (struct file_system_type*, 
                                        int, const char*, void *);
        
        void (*kill_sb) (struct super_block *);  /*终止访问超级块*/            
        struct module *owner;                    /*文件系统模块*/
        struct file_system_type * next;          /*链表中的下一个文件系统类型*/
        struct list_head fs_supers;              /*具有同一种文件系统类型的超级块对象链表*/
};

struct vfsmount
{
        struct list_head mnt_hash;               /*散列表*/
        struct vfsmount *mnt_parent;             /*父文件系统*/
        struct dentry *mnt_mountpoint;           /*安装点的目录项对象*/
        struct dentry *mnt_root;                 /*该文件系统的根目录项对象*/
        struct super_block *mnt_sb;              /*该文件系统的超级块*/
        struct list_head mnt_mounts;             /*子文件系统链表*/
        struct list_head mnt_child;              /*子文件系统链表*/
        atomic_t mnt_count;                      /*使用计数*/
        int mnt_flags;                           /*安装标志*/
        char *mnt_devname;                       /*设备文件名*/
        struct list_head mnt_list;               /*描述符链表*/
        struct list_head mnt_fslink;             /*具体文件系统的到期列表*/
        struct namespace *mnt_namespace;         /*相关的名字空间*/
};

和进程相关

打开的文件集

struct files_struct {//打开的文件集
         atomic_t count;              /*结构的使用计数*/
        ……
         int max_fds;                 /*文件对象数的上限*/
        int max_fdset;               /*文件描述符的上限*/
        int next_fd;                 /*下一个文件描述符*/
        struct file ** fd;           /*全部文件对象数组*/
        ……
 };

struct fs_struct {//建立进程与文件系统的关系
         atomic_t count;              /*结构的使用计数*/
        rwlock_t lock;               /*保护该结构体的锁*/
        int umask;                  /*默认的文件访问权限*/
        struct dentry * root;        /*根目录的目录项对象*/
        struct dentry * pwd;         /*当前工作目录的目录项对象*/
        struct dentry * altroot;    /*可供选择的根目录的目录项对象*/
        struct vfsmount * rootmnt;   /*根目录的安装点对象*/
        struct vfsmount * pwdmnt;    /*pwd的安装点对象*/
        struct vfsmount * altrootmnt;/*可供选择的根目录的安装点对象*/
};

和路径查找相关

辅助查找

struct nameidata {
        struct dentry  *dentry;     /*目录项对象的地址*/
        struct vfsmount  *mnt;      /*安装点的数据*/
        struct qstr  last;          /*路径中的最后一个component*/
        unsigned int  flags;        /*查找标识*/
        int  last_type;             /*路径中的最后一个component的类型*/
        unsigned  depth;            /*当前symbolic link的嵌套深度,不能大于6*/
        char   *saved_names[MAX_NESTED_LINKS + 1];/
                                    /*和嵌套symbolic link 相关的pathname*/
        union {
            struct open_intent open; /*说明文件该如何访问*/
        } intent;   /*专用数据*/
};

 

对象间的联系

如上的数据结构并不是孤立存在的。正是通过它们的有机联系,VFS才能正常工作。如下的几张图是对它们之间的联系的描述。

如图5所示,被Linux支持的文件系统,都有且仅有一个file_system_type结构而不管它有零个或多个实例被安装到系统 中。每安装一个文件系统,就对应有一个超级块和安装点。超级块通过它的一个域s_type指向其对应的具体的文件系统类型。具体的 文件系统通过file_system_type中的一个域fs_supers链接具有同一种文件类型的超级块。同一种文件系统类型的超级块通过域s_instances链 接。

超级块、安装点和具体的文件系统的关系

图片示例_超级块,安装点和具体的文件系统的关系

从图可知:进程通过task_struct中的一个域files_struct files来了解它当前所打开的文件对象;而我们通常所说的文件 描述符其实是进程打开的文件对象数组的索引值。文件对象通过域f_dentry找到它对应的dentry对象,再由dentry对象的域d_inode找 到它对应的索引结点,这样就建立了文件对象与实际的物理文件的关联。最后,还有一点很重要的是, 文件对象所对应的文件操作函数 列表是通过索引结点的域i_fop得到的。图6对第三部分源码的理解起到很大的作用。

进程与超级块、文件、索引结点、目录项的关系

图片示例_进程与超级块,文件,索引结点,目录项的关系

 

基于 VFS 的文件I/O

到目前为止,文章主要都是从理论上来讲述VFS的运行机制;接下来我们将深入源代码层中,通过阐述两个具有代表性的系统 调用sys_open()和sys_read()来更好地理解VFS向具体文件系统提供的接口机制。由于本文更关注的是文件操作的整个流程体制,所以我 们在追踪源代码时,对一些细节性的处理不予关心。又由于篇幅所限,只列出相关代码。本文中的源代码来自于linux-2.6.17内核版本。

在深入sys_open()和sys_read()之前,我们先概览下调用sys_read()的上下文。图7描述了从用户空间的read()调用到数据从 磁盘读出的整个流程。当在用户应用程序调用文件I/O read()操作时,系统调用sys_read()被激发,sys_read()找到文件所在的具体文件 系统,把控制权传给该文件系统,最后由具体文件系统与物理介质交互,从介质中读出数据。

从物理介质读数据的过程

图片示例_从物理介质读数据的过程

 

解决问题

跨文件系统的文件操作的基本原理

到此,我们也就能够解释在Linux中为什么能够跨文件系统地操作文件了。举个例子,将vfat格式的磁盘上的一个文件a.txt拷贝到ext3格式的磁 盘上,命名为b.txt。这包含两个过程,对a.txt进行读操作,对b.txt进行写操作。读写操作前,需要先打开文件。由前面的分析可知,打开文件 时,VFS会知道该文件对应的文件系统格式,以后操作该文件时,VFS会调用其对应的实际文件系统的操作方法。所以,VFS调用vfat的读文件方法将 a.txt的数据读入内存;在将a.txt在内存中的数据映射到b.txt对应的内存空间后,VFS调用ext3的写文件方法将b.txt写入磁盘;从而 实现了最终的跨文件系统的复制操作。

 

“一切皆是文件”的实现根本”

不论是普通的文件,还是特殊的目录、设备等,VFS都将它们同等看待成文件,通过同一套文件操作界面来对它们进行操作。操作文件时需先打开;打开文件 时,VFS会知道该文件对应的文件系统格式;当VFS把控制权传给实际的文件系统时,实际的文件系统再做出具体区分,对不同的文件类型执行不同的操作。这 也就是“一切皆是文件”的根本所在。

 

总结

VFS即虚拟文件系统是Linux文件系统中的一个抽象软件层;因为它的支持,众多不同的实际文件系统才能在Linux中共存,跨文件系统操作才能实现。 VFS借助它四个主要的数据结构即超级块、索引节点、目录项和文件对象以及一些辅助的数据结构,向Linux中不管是普通的文件还是目录、设备、套接字等 都提供同样的操作界面,如打开、读写、关闭等。只有当把控制权传给实际的文件系统时,实际的文件系统才会做出区分,对不同的文件类型执行不同的操作。由此 可见,正是有了VFS的存在,跨文件系统操作才能执行,Unix/Linux中的“一切皆是文件”的口号才能够得以实现。

 

 

七、文件系统管理相关命令

 

相关命令

fdisk        # Linux分区表操作工具软件  
mke2fs       # 创建ext2/ext3/ext4文件系统  
blkid        # 定位或打印块设备属性信息  
e2lable      # 改变ext2/ext3/ext4文件系统的卷标  
tune2fs      # 调整文件系统参数信息  
dumpe2fs     # 显示文件系统超级块信息和块组描述符  
fsck         # 检查并修复Linux文件系统  
e2fsck       # 检查并修复ext系列文件系统  
mount        # 挂载文件系统  
fuser        # 报告进程使用的文件或是网络套接字  
free         # 显示系统中已用的和未用的内存总和  
du           # 报告磁盘空间使用情况  
df           # 报告文件系统磁盘空间的使用情况  
dd           # 复制文件并对原文件进行转化和格式化处理  
mknod        # 创建块设备文件或字符设备文件  

 

1、fdisk (Linux分区操作)

fdisk - Partition table manipulator for Linux    # Linux分区表操作工具软件
 
SYNOPSIS
       fdisk [-uc] [-b sectorsize] [-C cyls] [-H heads] [-S sects] device
 
交互式命令   
    m:显示帮助信息 
    p: 显示当前硬件的分区,包括没保存的改动
    n: 创建新分区,e: 扩展分区,p: 主分区
    d: 删除一个分区
    w: 保存退出
    q: 不保存退出
    t: 修改分区类型,L: 查看所有支持的分区类型
    l: 显示所有支持的分区类型
 
[root@soysauce ~]# fdisk /dev/sdb            
 
WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
         switch off the mode (command 'c') and change display units to
         sectors (command 'u').
 
Command (m for help): p                    # 显示所有的分区
 
Disk /dev/sdb: 21.5 GB, 21474836480 bytes
255 heads, 63 sectors/track, 2610 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x84c99918
 
   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1         262     2104483+  83  Linux
 
Command (m for help): n                        # 新建一个分区
Command action
   e   extended
   p   primary partition (1-4)
p                                               # 建立主分区
Partition number (1-4): 2                      # 指定分区号
First cylinder (263-2610, default 263):         # 分区起始柱面,默认即可
Using default value 263
Last cylinder, +cylinders or +size{K,M,G} (263-2610, default 2610): +3G # 分区结束柱面,可直接指定大小
 
Command (m for help): t                        # 修改分区类型
Partition number (1-4): 2
Hex code (type L to list codes): L             # 输入t之后是L选项,如果直接查看则是l
 
 0  Empty           24  NEC DOS         81  Minix / old Lin bf  Solaris        
 1  FAT12           39  Plan 9          82  Linux swap / So c1  DRDOS/sec (FAT-
 2  XENIX root      3c  PartitionMagic  83  Linux           c4  DRDOS/sec (FAT-
 3  XENIX usr       40  Venix 80286     84  OS/2 hidden C:  c6  DRDOS/sec (FAT-
 4  FAT16 <32M      41  PPC PReP Boot   85  Linux extended  c7  Syrinx         
 5  Extended        42  SFS             86  NTFS volume set da  Non-FS data    
 6  FAT16           4d  QNX4.x          87  NTFS volume set db  CP/M / CTOS / .
 7  HPFS/NTFS       4e  QNX4.x 2nd part 88  Linux plaintext de  Dell Utility   
 8  AIX             4f  QNX4.x 3rd part 8e  Linux LVM       df  BootIt         
 9  AIX bootable    50  OnTrack DM      93  Amoeba          e1  DOS access     
 a  OS/2 Boot Manag 51  OnTrack DM6 Aux 94  Amoeba BBT      e3  DOS R/O        
 b  W95 FAT32       52  CP/M            9f  BSD/OS          e4  SpeedStor      
 c  W95 FAT32 (LBA) 53  OnTrack DM6 Aux a0  IBM Thinkpad hi eb  BeOS fs        
 e  W95 FAT16 (LBA) 54  OnTrackDM6      a5  FreeBSD         ee  GPT            
 f  W95 Ext'd (LBA) 55  EZ-Drive        a6  OpenBSD         ef  EFI (FAT-12/16/
10  OPUS            56  Golden Bow      a7  NeXTSTEP        f0  Linux/PA-RISC b
11  Hidden FAT12    5c  Priam Edisk     a8  Darwin UFS      f1  SpeedStor      
12  Compaq diagnost 61  SpeedStor       a9  NetBSD          f4  SpeedStor      
14  Hidden FAT16 <3 63  GNU HURD or Sys ab  Darwin boot     f2  DOS secondary  
16  Hidden FAT16    64  Novell Netware  af  HFS / HFS+      fb  VMware VMFS    
17  Hidden HPFS/NTF 65  Novell Netware  b7  BSDI fs         fc  VMware VMKCORE 
18  AST SmartSleep  70  DiskSecure Mult b8  BSDI swap       fd  Linux raid auto
1b  Hidden W95 FAT3 75  PC/IX           bb  Boot Wizard hid fe  LANstep        
1c  Hidden W95 FAT3 80  Old Minix       be  Solaris boot    ff  BBT            
1e  Hidden W95 FAT1
Hex code (type L to list codes): 82
Changed system type of partition 2 to 82 (Linux swap / Solaris)
 
Command (m for help): w                        # 保存退出
The partition table has been altered!
 
Calling ioctl() to re-read partition table.
 
WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)
Syncing disks.
[root@soysauce ~]# cat /proc/partitions     # 查看当前内核已识别的分区
major minor  #blocks  name
 
   8        0   20971520 sda
   8        1     512000 sda1
   8        2   20458496 sda2
   8       16   20971520 sdb
   8       17    2104483 sdb1
 253        0   18423808 dm-0
 253        1    2031616 dm-1
[root@soysauce ~]# partx -a /dev/sdb   # 通知内核重读分区表信息,RHEL5或者CentOS上一般是partprobe命令
BLKPG: Device or resource busy
error adding partition 1
[root@soysauce ~]# cat /proc/partitions 
major minor  #blocks  name
 
   8        0   20971520 sda
   8        1     512000 sda1
   8        2   20458496 sda2
   8       16   20971520 sdb
   8       17    2104483 sdb1
   8       18    3156772 sdb2                # 此时sdb2已经读取到了
 253        0   18423808 dm-0
 253        1    2031616 dm-1
[root@soysauce ~]# mkswap -L MYDATA/dev/sdb2                # 格式化交换分区
Setting up swapspace version 1, size = 3156768 KiB
LABEL=MYDATA, UUID=2f0ca25b-e6f8-45ae-a239-00f5b38f7275
[root@soysauce ~]# free -m
             total       used       free     shared    buffers     cached
Mem:           988        176        812          0         67         37
-/+ buffers/cache:         71        917
Swap:         1983          0       1983            # 此时还未启用刚才创建的那个交换分区
[root@soysauce ~]# swapon /dev/sdb2                 # 启用刚刚创建的交换分区
[root@soysauce ~]# free -m
             total       used       free     shared    buffers     cached
Mem:           988        178        810          0         67         37
-/+ buffers/cache:         73        915
Swap:         5066          0       5066            # 此时可以看到已然生效
[root@soysauce ~]# swapoff /dev/sdb2                # 关闭交换分区
[root@soysauce ~]# free -m
             total       used       free     shared    buffers     cached
Mem:           988        176        812          0         67         37
-/+ buffers/cache:         71        917
Swap:         1983          0       1983            # 此时可以看到已然关闭

 

2、mke2fs (创建ext2/ext3/ext4文件系统)

mke2fs - create an ext2/ext3/ext4 filesystem    # 创建ext2/ext3/ext4文件系统
 
SYNOPSIS
       mke2fs [options] DEVICE
    
    -j:创建ext3类型文件系统
    -b BLOCK_SIZE:指定块大小,默认为4096;可用取值为1024、2048或4096
    -L LABEL:指定分区卷标
    -m #:指定预留给超级用户的块数百分比,默认值为%5
    -i #:用于指定为多少字节的空间创建一个inode,默认为8192;应为block的2^n倍
    -t FSTYPE:指定文件系统类型
    -N #:指定inode个数
    -F:强制创建文件系统,不管其是否处于挂载状态
    -E:用户指定额外文件系统属性
    -q:执行时不显示任何信息,常用于脚本
    -c:检查是否有损坏的区块
 
[root@soysauce ~]# fdisk /dev/sdb             # 创建一个分区完整过程
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with disk identifier 0x84c99918.
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.
 
Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)
 
WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
         switch off the mode (command 'c') and change display units to
         sectors (command 'u').
 
Command (m for help): n                # 新建一个分区
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1                # 自己选择分区号,1-4中选
First cylinder (1-2610, default 1): 
Using default value 1
Last cylinder, +cylinders or +size{K,M,G} (1-2610, default 2610): +2G
 
Command (m for help): w                 # 保存创建的分区并退出
The partition table has been altered!
 
Calling ioctl() to re-read partition table.
Syncing disks.
[root@soysauce ~]# cat /proc/partitions         # 查看当前内核已经读取到的分区信息
major minor  #blocks  name
 
   8        0   20971520 sda
   8        1     512000 sda1
   8        2   20458496 sda2
   8       16   20971520 sdb
   8       17    2104483 sdb1 # 我这里内核已经读取到了sdb1,而在CentOS5上可能需要执行prartprobe命令  
 253        0   18423808 dm-0
 253        1    2031616 dm-1
[root@soysauce ~]# mke2fs -j /dev/sdb1         # 创建ext3格式的文件系统
mke2fs 1.41.12 (17-May-2010)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
131648 inodes, 526120 blocks
26306 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=541065216
17 block groups
32768 blocks per group, 32768 fragments per group
7744 inodes per group
Superblock backups stored on blocks: 
    32768, 98304, 163840, 229376, 294912
 
Writing inode tables: done                            
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done
 
This filesystem will be automatically checked every 24 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
[root@soysauce ~]# mke2fs -t ext4 /dev/sdb1        # 创建ext4格式的文件系统
mke2fs 1.41.12 (17-May-2010)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
131648 inodes, 526120 blocks
26306 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=541065216
17 block groups
32768 blocks per group, 32768 fragments per group
7744 inodes per group
Superblock backups stored on blocks: 
    32768, 98304, 163840, 229376, 294912
 
Writing inode tables: done                            
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done
 
This filesystem will be automatically checked every 20 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.

 

3、blkid (定位或打印块设备属性信息)

blkid - command-line utility to locate/print block device attributes # 定位或打印块设备属性信息
 
SYNOPSIS
       blkid [options] [DEVICE]
        
    -s <tag>:显示指定信息,默认显示所有信息
    -o format:指定显示格式,常用list
 
[root@soysauce ~]# blkid 
/dev/sda1: UUID="7a79d653-e9b7-43f2-a2c1-e41af29b3f5d" TYPE="ext4" 
/dev/sda2: UUID="aNiMxY-uTa4-IcVC-1FD7-i2S9-kwnV-lF4BMS" TYPE="LVM2_member" 
/dev/mapper/vg_centos6-lv_root: UUID="09b9916a-7424-4be3-9dc8-5222b699ef33" TYPE="ext4" 
/dev/mapper/vg_centos6-lv_swap: UUID="2a88de6d-5333-4077-b13e-117bbf60c5d6" TYPE="swap" 
[root@soysauce ~]# blkid -o device            # 只显示设备名
/dev/sda1
/dev/sda2
/dev/mapper/vg_centos6-lv_root
/dev/mapper/vg_centos6-lv_swap
[root@soysauce ~]# blkid -s UUID /dev/sda1       # 只显示/dev/sda1的UUID
/dev/sda1: UUID="7a79d653-e9b7-43f2-a2c1-e41af29b3f5d"

 

4、e2lable(改变ext2/ext3/ext4文件系统的卷标)

e2label - Change the label on an ext2/ext3/ext4 filesystem    # 改变ext2/ext3/ext4文件系统的卷标
 
SYNOPSIS
       e2label device [ new-label ]
         
[root@soysauce ~]# e2label /dev/sdb1 SOYSAUCE          # 修改/dev/sdb1卷标
[root@soysauce ~]# e2label /dev/sdb1             # 查看/dev/sdb1卷标
SOYSAUCE

 

5、tune2fs(调整文件系统参数信息)

tune2fs - adjust tunable filesystem parameters on ext2/ext3/ext4 filesystems # 调整文件系统参数信息
 
SYNOPSIS
       tune2fs  [options]   DEVICE
        
    -j:不损害原有数据,将ext2升级至ext3
    -L LABEL:设定或修改卷标
    -m #:调整预留百分比
    -r #:指定预留块数
    -o:设定默认挂载选项,常用的acl
    -c #:指定挂载次数达到#次之后进行自检,0或-1表关闭此功能
    -C #:指定文件系统已经被挂载的次数
    -i #:每挂载使用多少天后进行自检;0或-1表示关闭此功能
    -l:显示超级块中的信息
     
[root@soysauce ~]# tune2fs -j /dev/sdb1    # 无损升级至ext3文件系统
tune2fs 1.41.12 (17-May-2010)
Creating journal inode: done
This filesystem will be automatically checked every 22 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
[root@soysauce ~]# blkid /dev/sdb1
/dev/sdb1: UUID="79d72bb3-9b67-45cd-8e77-2b37349db88c" SEC_TYPE="ext2" TYPE="ext3" 
[root@soysauce ~]# tune2fs -m 8 /dev/sdb1    # 调整预留块百分比为%8
tune2fs 1.41.12 (17-May-2010)
Setting reserved blocks percentage to 8% (42089 blocks)
[root@soysauce ~]# tune2fs -l  /dev/sdb1    # 查看超级块信息
tune2fs 1.41.12 (17-May-2010)
Filesystem volume name:   <none>
Last mounted on:          <not available>
Filesystem UUID:          79d72bb3-9b67-45cd-8e77-2b37349db88c
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:     has_journal ext_attr resize_inode dir_index filetype sparse_super large_file
Filesystem flags:         signed_directory_hash 
Default mount options:    (none)
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              131648
Block count:              526120
Reserved block count:     42089
Free blocks:              500671
Free inodes:              131637
First block:              0
Block size:               4096
Fragment size:            4096
Reserved GDT blocks:      128
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         7744
Inode blocks per group:   484
Filesystem created:       Mon Nov 23 20:24:17 2015
Last mount time:          n/a
Last write time:          Mon Nov 23 20:26:43 2015
Mount count:              0
Maximum mount count:      22
Last checked:             Mon Nov 23 20:24:17 2015
Check interval:           15552000 (6 months)
Next check after:         Sat May 21 20:24:17 2016
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:              256
Required extra isize:     28
Desired extra isize:      28
Journal inode:            8
Default directory hash:   half_md4
Directory Hash Seed:      98e59dee-37cb-4cf4-96bb-47ab22e61c0d
Journal backup:           inode blocks

 

6、dumpe2fs(显示文件系统超级块信息和块组描述符)

dumpe2fs - dump ext2/ext3/ext4 filesystem information    # 显示文件系统超级块信息和块组描述符
 
SYNOPSIS
        dumpe2fs  [options]  DEVICE
            
    -h:查看超级块信息,但不包括GDT(块组描述表)
        
[root@soysauce ~]# dumpe2fs -h /dev/sdb1      # 查看超级块信息,不显示GDT
dumpe2fs 1.41.12 (17-May-2010)
Filesystem volume name:   <none>
Last mounted on:          <not available>
Filesystem UUID:          79d72bb3-9b67-45cd-8e77-2b37349db88c
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype sparse_super large_file
Filesystem flags:         signed_directory_hash 
Default mount options:    (none)
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              131648
Block count:              526120
Reserved block count:     42089
Free blocks:              500671
Free inodes:              131637
First block:              0
Block size:               4096
Fragment size:            4096
Reserved GDT blocks:      128
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         7744
Inode blocks per group:   484
Filesystem created:       Mon Nov 23 20:24:17 2015
Last mount time:          n/a
Last write time:          Mon Nov 23 20:26:43 2015
Mount count:              0
Maximum mount count:      22
Last checked:             Mon Nov 23 20:24:17 2015
Check interval:           15552000 (6 months)
Next check after:         Sat May 21 20:24:17 2016
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:              256
Required extra isize:     28
Desired extra isize:      28
Journal inode:            8
Default directory hash:   half_md4
Directory Hash Seed:      98e59dee-37cb-4cf4-96bb-47ab22e61c0d
Journal backup:           inode blocks
Journal features:         (none)
Journal size:             64M
Journal length:           16384
Journal sequence:         0x00000001
Journal start:            0

 

7、fsck(检查并修复Linux文件系统)

fsck - check and repair a Linux file system    # 检查并修复Linux文件系统
 
SYNOPSIS 
    -a:自动修复
    -t FSTYPE:指定文件系统类型,可以不指,但一定不能指错
 
[root@soysauce ~]# fsck /dev/sdb1        # 我这里文件系统是clean状态,所以没有检查
fsck from util-linux-ng 2.17.2
e2fsck 1.41.12 (17-May-2010)
/dev/sdb1: clean, 11/131648 files, 25449/526120 blocks

 

8、e2fsck(检查并修复ext系列文件系统)

e2fsck - check a Linux ext2/ext3/ext4 file system    # 检查并修复ext系列文件系统
 
SYNOPSIS
       e2fsck  [options]  DEVICE
 
    -f:强制检查
    -p:自动修复
              
[root@soysauce ~]# e2fsck /dev/sdb1            
e2fsck 1.41.12 (17-May-2010)
/dev/sdb1: clean, 11/131648 files, 25449/526120 blocks
[root@soysauce ~]# e2fsck  -f /dev/sdb1        # 强制检查文件系统
e2fsck 1.41.12 (17-May-2010)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/sdb1: 11/131648 files (0.0% non-contiguous), 25449/526120 blocks

 

9、mount(挂载文件系统)

mount - mount a filesystem        # 挂载文件系统
 
SYNOPSIS
            mount [options] [-o options] DEVICE MOUNT_POINT 
                   
    -a:表示挂载/etc/fstab文件中定义的所有文件系统
    -n:默认情况下,mount命令每挂载一个设备,都会把挂载的设备信息保存至/etc/mtab文件;使用—n选项意味着挂载设备时,不把信息写入此文件
    -t FSTYPE:指定正在挂载设备上的文件系统的类型;不使用此选项时,mount会调用blkid命令获取对应文件系统的类型
    -r:只读挂载,挂载光盘时常用此选项
    -w:读写挂载
    -o:指定额外的挂载选项,也即指定文件系统启用的属性;
        remount:重新挂载当前文件系统
        ro:挂载为只读
        rw:读写挂载
        loop:挂载本地回环设备
 
挂载:将新的文件系统关联至当前根文件系统
卸载:将某文件系统与当前根文件系统的关联关系预以移除
 
[root@soysauce ~]# mount          # 不带任何参数的mount命令可以显示当前已挂载的文件系统
/dev/mapper/vg_centos6-lv_root on / type ext4 (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
tmpfs on /dev/shm type tmpfs (rw)
/dev/sda1 on /boot type ext4 (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
[root@soysauce ~]# mount -o ro /dev/sdb1 /mnt/    # 以只读方式挂载
[root@soysauce ~]# echo "hello" >> /mnt/a.txt
-bash: /mnt/a.txt: Read-only file system           # 不能写文件
[root@soysauce ~]# mount -o remount,rw  /mnt/       # 以可读写方式重新挂载
[root@soysauce ~]# echo "hello" >> /mnt/a.txt        
[root@soysauce ~]# cd /mnt/
[root@soysauce mnt]# ls
a.txt  lost+found
[root@soysauce mnt]# cat a.txt            # 写入成功
hello
[root@soysauce ~]# cat /etc/fstab
LABEL=/ / ext3 defaults,barrier=0 1 1
tmpfs                   /dev/shm                tmpfs   defaults        0 0
devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
sysfs                   /sys                    sysfs   defaults        0 0
proc                    /proc                   proc    defaults        0 0
要挂载的设备      挂载点      文件系统类型     挂载选项     转储频率(每多少天做一次完全备份)     文件系统检测次序(只有根可以为1)

 

10、fuser(报告进程使用的文件或是网络套接字)

fuser - identify processes using files or sockets    # 报告进程使用的文件或是网络套接字
 
SYNOPSIS
       fuser  [options]  DEVICE
        
    -v:查看某文件上正在运行的进程
    -k:杀死正在访问某文件的进程
    -m:显示访问挂载点的进程
 
[root@soysauce ~]# mount /dev/sdb1 /mnt/    # 挂载/dev/sdb1至/mnt目录下
[root@soysauce ~]# cd /mnt/                # 切换进/mnt目录
[root@soysauce mnt]# umount /mnt/        # 此时我就站在/mnt目录下,卸载肯定卸不掉
umount: /mnt: device is busy.
        (In some cases useful info about processes that use
         the device is found by lsof(8) or fuser(1))
[root@soysauce mnt]# fuser -km /mnt/      # 强行结束正在访问/mnt挂载点的进程,然后直接把我踢下线了...
/mnt/:                1860c
 
Connection closed by foreign host.
 
Disconnected from remote host(CentOS6.5) at 22:20:33.
 
Type `help' to learn how to use Xshell prompt. 

 

11、free(显示系统中已用的和未用的内存总和)

free - Display amount of free and used memory in the system    # 显示系统中已用的和未用的内存总和
 
SYNOPSIS
       free [-b | -k | -m] [-o] [-s delay ] [-t] [-l] [-V]
 
        -m:以M为单位来显示
 
[root@soysauce ~]# free -m
             total       used       free     shared    buffers     cached
Mem:           988        176        812          0         67         37
-/+ buffers/cache:         71        917    
Swap:         1983          0       1983        
第一行:内存总大小、已使用空间大小、剩余空间大小、共享内存、缓冲数据大小、缓存数据大小
第二行:UsedMem-(buffers+cached)为真实使用空间、FreeMem+(buffers+cached)为真实剩余空间
第三行:总交换分区大小、已使用交换分区大小、剩余交换分区大小

 

12、du(报告磁盘空间使用情况)

du - estimate file space usage        # 报告磁盘空间使用情况
 
SYNOPSIS
       du [OPTION]... [FILE]...
       du [OPTION]... --files0-from=F
 
    -s:仅显示总计,只列出最后加总的值
    -h:做单位换算的
 
[root@soysauce ~]# du -sh /root/        # 统计总大小
1.3M    /root/    
[root@soysauce ~]# du -h /root/         # 统计目录下每单个文件大小
4.0K    /root/.pki/nssdb
8.0K    /root/.pki
4.0K    /root/.ansible/cp
8.0K    /root/.ansible
8.0K    /root/test
36K /root/.vim/syntax
48K /root/.vim
20K /root/.ssh
136K    /root/scripts
1.3M    /root/

 

13、df(报告文件系统磁盘空间的使用情况)

df - report file system disk space usage        # 报告文件系统磁盘空间的使用情况
 
SYNOPSIS
       df [OPTION]... [FILE]...
        
    -a:查看所有的文件系统
    -h:做单位换算
    -i:显示inode使用情况
    -P:以POSIX风格显示
    -T:显示文件系统类型
 
[root@soysauce ~]# df -ihT            # 显示Inode使用情况
Filesystem                     Type  Inodes IUsed IFree IUse% Mounted on
/dev/mapper/vg_centos6-lv_root ext4    1.1M   40K  1.1M    4% /
tmpfs                          tmpfs   124K     1  124K    1% /dev/shm
/dev/sda1                      ext4    126K    38  125K    1% /boot
/dev/sdb1                      ext3    129K    12  129K    1% /mnt
[root@soysauce ~]# df -hT            # 显示磁盘空间使用情况
Filesystem                     Type   Size  Used Avail Use% Mounted on
/dev/mapper/vg_centos6-lv_root ext4    18G  2.3G   15G  14% /
tmpfs                          tmpfs  495M     0  495M   0% /dev/shm
/dev/sda1                      ext4   485M   33M  427M   8% /boot
/dev/sdb1                      ext3   2.0G   68M  1.8G   4% /mnt

 

14、dd(复制文件并对原文件进行转化和格式化处理)

dd - convert and copy a file        # 复制文件并对原文件进行转化和格式化处理
 
SYNOPSIS
       dd [OPERAND]...
       dd OPTION
 
    if=数据来源
    of=数据存储目录
    bs=#:指定块大小,单位默认为字节,也可以指定M、G等
    count=#:指定读取的块数
    seek=#:创建数据文件时,跳过的空间大小
 
[root@soysauce ~]# dd if=/dev/sda of=/root/mbr.back bs=512 count=1    # 备份mbr
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000675345 s, 758 kB/s
[root@soysauce ~]# dd if=/dev/zero of=/root/zerofile bs=1M count=1 seek=1023    # 跳过前面1023M,创建一个假的1G文件
1+0 records in
1+0 records out
1048576 bytes (1.0 MB) copied, 0.00649022 s, 162 MB/s
[root@soysauce ~]# ll -h /root/zerofile     # ls看到的是假的1G
-rw-r--r-- 1 root root 1.0G Nov 24 11:07 /root/zerofile
[root@soysauce ~]# du -sh /root/zerofile     # du看到的是真实的大小,为1M
1.0M    /root/zerofile

 

15、mknod(创建块设备文件或字符设备文件)

mknod - make block or character special files        # 创建块设备文件或字符设备文件
 
SYNOPSIS
       mknod [OPTION]... NAME TYPE [MAJOR MINOR]
 
    -m:设置权限
    -Z:设置安全的上下文
         
[root@soysauce ~]# mknod /dev/mydev b 65 0        # 创建一个主设备号为65 次设备号为0的块设备文件
[root@soysauce ~]# ll /dev/mydev 
brw-r--r-- 1 root root 65, 0 Nov 24 11:34 /dev/mydev
[root@soysauce ~]# mknod -m 600 /dev/mysdev b 65 1    # -m指定权限为600
[root@soysauce ~]# ll /dev/mysdev 
brw------- 1 root root 65, 1 Nov 24 11:36 /dev/mysdev

 

 

 

Linux 文件系统详解

 

一、文件系统层次分析

 

由上而下主要分为:用户层、VFS层、文件系统层、缓存层、块设备层、磁盘驱动层、磁盘物理层

  • 用户层:最上面用户层就是我们日常使用的各种程序,需要的接口主要是文件的创建、删除、打开、关闭、写、读等。 
  • VFS层:我们知道Linux分为用户态和内核态,用户态请求硬件资源需要调用System Call通过内核态去实现。用户的这些文件相关操作都有对应的System Call函数接口,接口调用 VFS对应的函数。 
  • 文件系统层:不同的文件系统实现了VFS的这些函数,通过指针注册到VFS里面。所以,用户的操作通过VFS转到各种文件系统。文件系统把文件读写命令转化为对磁盘LBA的操作,起了一个翻译和磁盘管理的作用。 
  • 缓存层:文件系统底下有缓存,Page Cache,加速性能。对磁盘LBA的读写数据缓存到这里。
  • 块设备层:块设备接口Block Device是用来访问磁盘LBA的层级,读写命令组合之后插入到命令队列,磁盘的驱动从队列读命令执行。Linux设计了电梯算法等对很多LBA的读写进行优化排序,尽量把连续地址放在一起。
  • 磁盘驱动层:磁盘的驱动程序把对LBA的读写命令转化为各自的协议,比如变成ATA命令,SCSI命令,或者是自己硬件可以识别的自定义命令,发送给磁盘控制器。Host Based SSD甚至在块设备层和磁盘驱动层实现了FTL,变成对Flash芯片的操作。 
  • 磁盘物理层:读写物理数据到磁盘介质。

 

 

二、文件系统结构与工作原理(主要以ext4为例)

 

我们都知道,windows文件系统主要有 fat、ntfs 等,而 linux 文件系统则种类多的很,主要有 VFS 做了一个软件抽象层,向上提供文件操作接口,向下提供标准接口供不同文件系统对接。

下面主要就以EXT4文件系统为例,讲解下文件系统结构与工作原理:

上面两个图大体呈现了ext4文件系统的结构,从中也相信能够初步的领悟到文件系统读写的逻辑过程。

下面对上图里边的构成元素做个简单的讲解:

  • 引导块:为磁盘分区的第一个块,记录文件系统分区的一些信息,引导加载当前分区的程序和数据被保存在这个块中。一般占用2kB,
  • 超级块:超级块用于存储文件系统全局的配置参数 (譬如:块大小,总的块数和inode数)和动态信息(譬如:当前空闲块数和inode数),其处于文件系统开始位置的1k处,所占大小为1k。为了系统的健壮性,最初每个块组都有超级块和组描述符表(以下将用GDT)的一个拷贝,但是当文件系统很大时,这样浪费了很多块(尤其是GDT占用的块多),后来采用了一种稀疏的方式来存储这些拷贝,只有块组号是3, 5 ,7的幂的块组(譬如说1,3,5,7,9,25,49…)才备份这个拷贝。通常情况下,只有主拷贝(第0块块组)的超级块信息被文件系统使用,其它拷贝只有在主拷贝被破坏的情况下才使用。
  • 块组描述符:GDT用于存储块组描述符,其占用一个或者多个数据块,具体取决于文件系统的大小。它主要包含块位图,inode位图和inode表位置,当前空闲块数,inode数以及使用的目录数(用于平衡各个块组目录数),具体定义可以参见ext3_fs.h文件中struct ext3_group_desc。每个块组都对应这样一个描述符,目前该结构占用32个字节,因此对于块大小为4k的文件系统来说,每个块可以存储128个块组描述符。由于GDT对于定位文件系统的元数据非常重要,因此和超级块一样,也对其进行了备份。GDT在每个块组(如果有备份)中内容都是一样的,其所占块数也是相同的。从上面的介绍可以看出块组中的元数据譬如块位图,inode位图,inode表其位置不是固定的,当然默认情况下,文件系统在创建时其位置在每个块组中都是一样的,如图2所示(假设按照稀疏方式存储,且n不是3,5,7的幂)
  • 块组:每个块组包含一个块位图块,一个 inode 位图块,一个或多个块用于描述 inode 表和用于存储文件数据的数据块,除此之外,还有可能包含超级块和所有块组描述符表(取决于块组号和文件系统创建时使用的参数)。下面将对这些元数据作一些简要介绍。
  • 块位图

块位图用于描述该块组所管理的块的分配状态。如果某个块对应的位未置位,那么代表该块未分配,可以用于存储数据;否则,代表该块已经用于存储数据或者该块不能够使用(譬如该块物理上不存在)。由于块位图仅占一个块,因此这也就决定了块组的大小。

Inode位图:

Inode位图用于描述该块组所管理的inode的分配状态。我们知道inode是用于描述文件的元数据,每个inode对应文件系统中唯一的一个号,如果inode位图中相应位置位,那么代表该inode已经分配出去;否则可以使用。由于其仅占用一个块,因此这也限制了一个块组中所能够使用的最大inode数量。

Inode表:

Inode表用于存储inode信息。它占用一个或多个块(为了有效的利用空间,多个inode存储在一个块中),其大小取决于文件系统创建时的参数,由于inode位图的限制,决定了其最大所占用的空间。

以上这几个构成元素所处的磁盘块成为文件系统的元数据块,剩余的部分则用来存储真正的文件内容,称为数据块,而数据块其实也包含数据和目录。

了解了文件系统的结构后,接下来我们来看看操作系统是如何读取一个文件的:

大体过程如下:

1、根据文件所在目录的inode信息,找到目录文件对应数据块

2、根据文件名从数据块中找到对应的inode节点信息

3、从文件inode节点信息中找到文件内容所在数据块块号

4、读取数据块内容

到这里,相信很多人会有一个疑问,我们知道一个文件只有一个Inode节点来存放它的属性信息,那么你可能会想如果一个大文件,那它的block一定是多个的,且可能不连续的,那么inode怎么来表示呢,下面的图告诉你答案:

 

 也就是说,如果文件内容太大,对应数据块数量过多,inode节点本身提供的存储空间不够,会使用其他的间接数据块来存储数据块位置信息,最多可以有三级寻址结构。

 到这里,应该都已经非常清楚文件读取的过程了,那么下面再抛出两个疑问:

1、文件的拷贝、剪切的底层过程是怎样的?

2、软连接和硬连接分别是如何实现的?

下面来结合stat命令动手操作一下,便知真相:

1)拷贝文件:创建一个新的inode节点,并且拷贝数据块内容

2)剪切文件:同个分区里边mv,inode节点不变,只是更新目录文件对应数据块里边的文件名和inode对应关系;跨分区mv,则跟拷贝一个道理,需要创建新的inode,因为inode节点不同分区是不能共享的。

3)软连接:创建软连接会创建一个新的inode节点,其对应数据块内容存储所链接的文件名信息,这样原文件即便删除了,重新建立一个同名的文件,软连接依然能够生效。

 4)硬链接:创建硬链接,并不会新建inode节点,只是links加1,还有再目录文件对应数据块上增加一条文件名和inode对应关系记录;只有将硬链接和原文件都删除之后,文件才会真正删除,即links为0才真正删除。

 

三、文件顺序读写和随机读写

 

从前面文章了解了磁盘工作原理之后,也已经明白了为什么文件随机读写速度会比顺序读写差很多,这个问题在windows里边更加明显,为什么呢?究其原因主要与文件系统工作机制有关,fat和ntfs文件系统设计上,每个文件所处的位置相对连续甚至紧靠在一起,这样没有为每个文件留下足够的扩展空间,因此容易产生磁盘碎片,用过windows系统的应该也知道,windows磁盘分区特别提供了磁盘碎片整理的高级功能。如下图:

那回过来,看看linux 文件系统ext4,都说linux不需要考虑磁盘碎片,究竟是怎么回事?

主要是因为Linux的文件系统会将文件分散在整个磁盘,在文件之间留有大量的自由空间,而不是像Windows那样将文件一个接一个的放置。当一个文件被编辑了并且变大了,一般都会有足够的自由空间来保存文件。如果碎片真的产生了,文件系统就会尝试在日常使用中将文件移动来减少碎片,所以不需要专门的碎片整理程序。但是,如果磁盘空间占用已经快满了,那碎片是不可避免的,文件系统的设计本来就是用来满足正常情况下使用的。如果磁盘空间不够,那要么就是数据冗余了,要么就该换容量更大的磁盘。你可以使用fsck命令来检测一下一个Linux文件系统的碎片化程度,只需要在输出中查看非连续i节点个数(non-contiguous inodes)就可以了。


关于文件系统的就讲这么多,下篇会讲解linux内核提供的一个资源管控机制cgroup,分析其原理及使用过程。

ext4文件系统bug:
http://www.phoronix.com/scan.php?page=news_item&px=MTIxNDQ

ext4文件系统描述:
http://blog.csdn.net/liangchen0322/article/details/50365685
http://blog.csdn.net/fybon/article/details/26243971
hexdump查看磁盘结构信息:
http://www.cnblogs.com/jiangcsu/p/5737659.html

 

 

linux 目录结构

 

鸟哥 Linux 私房菜:http://linux.vbird.org/linux_basic/0220filemanager.php

目录

/ 处于 linux 系统树形结构的最顶端,它是 linux 文件系统的入口,所有的目录、文件、设备都在 / 之下。
/binbin 是 Binary 的缩写,存放着 linux 系统命令。  ( ls、cat、mkdir 等 常用命令一般都在这里。 )
/boot系统启动相关的文件,如 内核、initrd,以及 grub(BootLoader)
/etc系统配置文件。
/home用户的家目录,每一个用户的家目录通常默认为 /home/USERNAME。在任一目录中执行 cd ~ 都可以返回到对应用户的家目录
/root管理员的家目录。即 超级用户(系统管理员)的主目录(特权阶级^o^)
/lib

这个目录里存放着系统最基本的动态链接共享库,包含许多被 /bin/ 和 /sbin/ 中的程序使用的库文件,目录 /usr/lib/ 中含有更多用于用户程序的库文件。作用类似于windows里的 DLL文件,几乎所有的应用程序都需要用到这些共享库。

库文件分为:静态库:单在程序中的库,其他程序不能使用该库文件。动态库:在内存中,任何用到该库的程序都可以使用

/lib/modules:内核模块文件

/media挂载点目录。linux 系统自动识别的一些设备,例如:U盘、光驱、移动硬盘等,linux 会把识别的设备挂载到这个目录下。

(在windows中,插入一张光盘,系统会自动读取光盘,用户可以直接执行,但在 linux中,插入光盘后需要在挂载点挂载这个设备之后才可以使用这个设备。)

/mnt

挂载点目录。系统提供这个目录是让用户临时挂载其他的文件系统。

系统提供该目录是为了让用户临时挂载别的文件系统的,可以将光驱挂载到/mnt/上,然后进入该目录就可以查看光驱里的内容。

/opt可选目录,第三方程序的安装目录。即安装软件时,软件所的目录,默认是空的。
/proc

伪文件系统,内核映射文件。即 虚拟文件系统目录,是系统内存的映射可直接访问这个目录来获取系统信息。

/proc 目录是 伪装的文件系统 proc挂载目录

操作系统运行时,进程(正在运行中的程序)信息 及 内核信息(比如cpu、硬盘分区、内存信息等)存放在这里。

proc 并不是真正的文件系统。因此,这个目录是一个虚拟的目录,它是系统内存的映射,可以直接访问这个目录来获取系统信息。

也就是说,这个目录的内容 不在硬盘上 而是 在内存里

/sys伪文件系统,跟硬件设备相关的属性映射文件
/tmp

/tmp 目录存放程序在运行时产生的信息和数据。但在引导启动后,运行的程序最好使用 /var/tmp 来代替 /tmp ,因为前者可能拥有一个更大的磁盘空间。

/var

用于存放运行时需要改变数据的文件,也是某些大文件的溢出区,比方说各种服务的日志文件(系统启动日志等。)等。

该目录的内容是经常变动的,/var下有 /var/log 目录用来存放系统日志的目录。/var/www 目录用来定义Apache服务器站点存放目录。/var/lib 用来存放一些库文件。

/lost+found这个目录平时是空的,系统非正常关机而留下 “无家可归” 的文件(windows下叫什么.chk)就在这里。默认为空,被FSCK(file system check用来检查和维护不一致的文件系统。若系统掉电或磁盘发生问题,可利用fsck命令对文件系统进行检查)用来放置零散文件(没有名称的文件)。当系统非法关机后,这里就会存放一些文件。
  
/sbin存放二进制可执行文件,只有 root 才能访问。这里存放的是系统管理员使用的系统级别的管理命令和程序。如 ifconfig 等。
/srv该目录存放一些服务启动之后需要提取的数据。
/dev

用于存放设备文件,即设备驱动程序,用户通过这些文件访问外部设备。比如,用户可以通过访问 /dev/mouse 来访问鼠标的输入,就像访问其他文件一样。

在 linux 中访问设备的方式和访问文件的方式是相同的。

/selinux这个目录是RedHat/CentOS所特有的目录,Selinux是一个安全机制,这个比较复杂,这个目录就是存放Selinux相关的文件的,一般我们安装操作系统的时候禁止使用它。
/usr

默认软件都会存于该目录下。用于存放系统应用程序,比较重要的目录 /usr/local 本地系统管理员软件安装目录(安装系统级的应用)。这是最庞大的目录,要用到的应用程序和文件几乎都在这个目录。 包括与系统用户直接有关的文件和目录,例如:应用程序及支持它们的库文件。类似于 windows下的 program files 目录。

/usr/x11r6              存放x window的目录

/usr/bin                  众多的应用程序  

/usr/sbin                超级用户的一些管理程序  

/usr/doc                 linux文档  

/usr/include           linux下开发和编译应用程序所需要的头文件  

/usr/lib                   常用的动态链接库和软件包的配置文件  

/usr/man               帮助文档  

/usr/src                 源代码,linux内核的源代码就放在 /usr/src/linux 里  

/usr/local/bin        本地增加的命令  

/usr/local/lib         本地增加的库

 

/etc 目录

特定主机系统范围内的配置文件。

  • /etc/init.d    这个目录是用来存放系统或服务器以System V模式启动的脚本,这在以System V模式启动或初始化的系统中常见。比如RedHat Fedora。
  • /etc/xinetd.d    如果服务器是通过xinetd模式运行的,它的脚本要放在这个目录下。有些系统没有这个目录,比如Slackware,有些老的版本也没有。在Redhat Fedora中比较新的版本中存在。
  • /etc/rc.d    这是Slackware发行版中有的一个目录,是BSD方式启动脚本的存放地,比如定义网卡,服务器开启脚本等。
  • /etc/X11    是X-Window相关的配置文件存放地。

目录

描述

/etc/rc /etc/rc.d

/etc/rc*.d

启动、或改变运行级时运行的scripts或scripts的目录.

/etc/hosts

本地域名解析文件

/etc/sysconfig/network

IP、掩码、网关、主机名配置

/etc/resolv.conf

DNS服务器配置

/etc/fstab

开机自动挂载系统,所有分区开机都会自动挂载

/etc/inittab

设定系统启动时Init进程将把系统设置成什么样的runlevel及加载相关的启动文件配置

/etc/exports

设置NFS系统用的配置文件路径

/etc/init.d

这个目录来存放系统启动脚本

/etc/profile/etc/csh.login,  /etc/csh.cshrc

全局系统环境配置变量

/etc/issue

认证前的输出信息,默认输出版本内核信息

/etc/motd

设置认证后的输出信息,

/etc/mtab

当前安装的文件系统列表.由scripts初始化,并由mount 命令自动更新.需要一个当前安装的文件系统的列表时使用,例如df 命令

/etc/group

类似/etc/passwd ,但说明的不是用户而是组.

/etc/passwd

用户数据库,其中的域给出了用户名、真实姓名、家目录、加密的口令和用户的其他信息.

/etc/shadow

在安装了影子口令软件的系统上的影子口令文件.影子口令文件将/etc/passwd 文件中的加密口令移动到/etc/shadow 中,而后者只对root可读.这使破译口令更困难.

/etc/sudoers

可以sudo命令的配置文件

/etc/syslog.conf

系统日志参数配置

/etc/login.defs

设置用户帐号限制的文件

/etc/securetty

确认安全终端,即哪个终端允许root登录.一般只列出虚拟控制台,这样就不可能(至少很困难)通过modem或网络闯入系统并得到超级用户特权.

/etc/printcap

类似/etc/termcap ,但针对打印机.语法不同.

/etc/shells

列出可信任的shell.chsh 命令允许用户在本文件指定范围内改变登录shell.提供一台机器FTP服务的服务进程ftpd 检查用户shell是否列在 /etc/shells 文件中,如果不是将不允许该用户登录.

/etc/xinetd.d

如果服务器是通过xinetd模式运行的,它的脚本要放在这个目录下。有些系统没有这个目录,比如Slackware,有些老的版本也没有。在Redhat Fedora中比较新的版本中存在。

/etc/opt/

/opt/的配置文件

/etc/X11/

X_Window系统(版本11)的配置文件

/etc/sgml/

SGML的配置文件

/etc/xml/

XML的配置文件

/etc/skel/

默认创建用户时,把该目录拷贝到家目录下

 

/usr 目录

默认软件都会存于该目录下。用于存储只读用户数据的第二层次;包含绝大多数的用户工具和应用程序。

  • /usr/local    这个目录一般是用来存放用户自编译安装软件的存放目录。一般是通过源码包安装的软件,如果没有特别指定安装目录的话,一般是安装在这个目录中。
  • /usr/lib    该目录和/lib目录相似,是库文件的存储目录。存放一些常用的共享库。
  • /usr/share    该目录用于存放系统共用的东西,比如/usr/share/fonts是字体目录,是用户都共用的。
  • /usr/share/doc    该目录是Linux共享文档的存放地。
  • /usr/share/man    该目录是共享的帮助文件的存放地。

目录

描述

/usr/X11R6

存放X-Windows的目录;

/usr/games

存放着XteamLinux自带的小游戏;

/usr/doc

Linux技术文档;

/usr/include

用来存放Linux下开发和编译应用程序所需要的头文件;

/usr/lib

存放一些常用的动态链接共享库和静态档案库;

/usr/man

帮助文档所在的目录;

/usr/src

Linux开放的源代码,就存在这个目录,爱好者们别放过哦;

/usr/bin/

非必要可执行文件 (在单用户模式中不需要);面向所有用户。

/usr/lib/

/usr/bin/和/usr/sbin/中二进制文件的

/usr/sbin/

非必要的系统二进制文件,例如:大量网络服务守护进程

/usr/share/

体系结构无关(共享)数据。

/usr/src/

源代码,例如:内核源代码及其头文件。

/usr/X11R6/

X Window系统版本 11, Release 6.

/usr/local/

本地数据的第三层次,具体到本台主机。通常而言有进一步的子目录,例如:bin/、lib/、share/.这是提供给一般用户的/usr目录,在这里安装一般的应用软件;

  • /usr/bin   这个目录是可执行程序的目录,普通用户就有权限执行。当我们从系统自带的软件包安装一个程序时,他的可执行文件大多会放在这个目录。相似的目录是/usr/local/bin目录。有时/usr/bin中的文件是/usr/local/bin的链接文件。
  • /usr/sbin  这个目录也是可执行程序的目录,但大多存放涉及系统管理的命令。只有root权限才能执行,相似目录是/sbin或/usr/local/sbin或/usr/X11R6/sbin等。
  • /usr/src   内核源码默认的放置目录

 

/var 目录

/var 包括系统一般运行时要改变的数据.每个系统是特定的,即不通过网络与其他计算机共享.

  • /var/adm    比如软件包安装信息、日志、管理信息等就存放在该目录下,在Slackware操作系统中是有这个目录的。在Fedora中好象没有。
  • /var/log    该目录用于存放系统日志。
  • /var/spool    打印机、邮件、代理服务器等假脱机目录存放在该目录下。

目录

描述

/var/log/message

日志信息,按周自动轮询

/var/spool/cron/root

定时器配置文件目录,默认按用户命名

/var/log/secure

记录登陆系统存取信息的文件,不管认证成功还是认证失败都会记录

/var/log/wtmp

记录登陆者信息的文件,last,who,w命令信息来源于此

/var/spool/clientmqueue/

当邮件服务未开启时,所有应发给系统管理员的邮件都将堆放在此

/var/spool/mail/

邮件目录

/var/tmp  

比/tmp 允许的大或需要存在较长时间的临时文件. (虽然系统管理员可能不允许/var/tmp 有很旧的文件.)

/var/lib  

系统正常运行时要改变的文件.  

/var/local  

/usr/local 中安装的程序的可变数据(即系统管理员安装的程序).注意,如果必要,即使本地安装的程序也会使用其他/var 目录,例如/var/lock .  

/var/lock  

锁定文件.许多程序遵循在/var/lock 中产生一个锁定文件的约定,以支持他们正在使用某个特定的设备或文件.其他程序注意到这个锁定文件,将不试图使用这个设备或文件.

/var/log/

各种程序的Log文件,特别是login   (/var/log/wtmp log所有到系统的登录和注销) 和syslog (/var/log/messages 里存储所有核心和系统程序信息. /var/log 里的文件经常不确定地增长,应该定期清除.  

/var/run  

保存到下次引导前有效的关于系统的信息文件.例如, /var/run/utmp 包含当前登录的用户的信息.

/var/cache/

应用程序缓存数据。这些数据是在本地生成的一个耗时的I/O或计算结果。应用程序必须能够再生或恢复数据。缓存的文件可以被删除而不导致数据丢失。

 

/proc 目录

Linux /proc目录详解:https://www.cnblogs.com/DswCnblog/p/5780389.html

Linux中/proc目录下文件详解:https://www.cnblogs.com/baiduboy/p/6098226.html

操作系统运行时,进程(正在运行中的程序)信息 及 内核信息(比如cpu、硬盘分区、内存信息等)存放在这里。

proc 并不是真正的文件系统。因此,这个目录是一个虚拟的目录,它是系统内存的映射,可以直接访问这个目录来获取系统信息。

也就是说,这个目录的内容 不在硬盘上 而是 在内存里

/proc/数字文件夹 :是一些进程相关的目录,每个目录中是对应进程本身相关信息的文件。

  • /proc/cpuinfo     关于处理器的信息,如类似、厂家、型号和性能等。比如cat /proc/cpuinfo
  • /proc/devices        当前运行内核所配置的所有设备清单。
  • /proc/filesystems   当前运行内核所配置的文件系统。
  • /proc/dma            当前正在使用的DMA通道。
  • /proc/interrupts    正在使用的中断和曾经有多少个中断。
  • /proc/ioports        当前正在使用的I/O端口。

 

/proc 目录下常见的文件介绍 

  • /proc/apm  高级电源管理(APM)版本信息及电池相关状态信息,通常由apm命令使用; 
  • /proc/buddyinfo  用于诊断内存碎片问题的相关信息文件; 
  • /proc/cmdline  在启动时传递至内核的相关参数信息,这些信息通常由lilo或grub等启动管理工具进行传递;
  • /proc/cpuinfo  处理器的相关信息的文件; 
  • /proc/crypto  系统上已安装的内核使用的密码算法及每个算法的详细信息列表; 
  • /proc/devices  系统已经加载的所有块设备和字符设备的信息,包含主设备号和设备组(与主设备号对应的设备类型)名; 
  • /proc/diskstats  每块磁盘设备的磁盘I/O统计信息列表;(内核2.5.69以后的版本支持此功能) 
  • /proc/dma  每个正在使用且注册的ISA DMA通道的信息列表; 
  • /proc/execdomains  内核当前支持的执行域(每种操作系统独特“个性”)信息列表; 
  • /proc/fb  帧缓冲设备列表文件,包含帧缓冲设备的设备号和相关驱动信息; 
  • /proc/filesystems  当前被内核支持的文件系统类型列表文件,被标示为nodev的文件系统表示不需要块设备的支持;通常mount一个设备时,如果没有指定文件系统类型将通过此文件来决定其所需文件系统的类型; 
  • /proc/interrupts  X86或X86_64体系架构系统上每个IRQ相关的中断号列表;多路处理器平台上每个CPU对于每个I/O设备均有自己的中断号;
  • /proc/iomem  每个物理设备上的记忆体(RAM或者ROM)在系统内存中的映射信息; 
  • /proc/ioports  当前正在使用且已经注册过的与物理设备进行通讯的输入-输出端口范围信息列表;如下面所示,第一列表示注册的I/O端口范围,其后表示相关的设备; 
  • /proc/kallsyms  模块管理工具用来动态链接或绑定可装载模块的符号定义,由内核输出;(内核2.5.71以后的版本支持此功能);通常这个文件中的信息量相当大; 
  • /proc/kcore  系统使用的物理内存,以ELF核心文件(core file)格式存储,其文件大小为已使用的物理内存(RAM)加上4KB;这个文件用来检查内核数据结构的当前状态,因此,通常由GBD通常调试工具使用,但不能使用文件查看命令打开此文件; 
  • /proc/kmsg  此文件用来保存由内核输出的信息,通常由/sbin/klogd或/bin/dmsg等程序使用,不要试图使用查看命令打开此文件;
  • /proc/loadavg  保存关于CPU和磁盘I/O的负载平均值,其前三列分别表示每1秒钟、每5秒钟及每15秒的负载平均值,类似于uptime命令输出的相关信息;第四列是由斜线隔开的两个数值,前者表示当前正由内核调度的实体(进程和线程)的数目,后者表示系统当前存活的内核调度实体的数目;第五列表示此文件被查看前最近一个由内核创建的进程的PID;
  • /proc/locks  保存当前由内核锁定的文件的相关信息,包含内核内部的调试数据;每个锁定占据一行,且具有一个惟一的编号;如下输出信息中每行的第二列表示当前锁定使用的锁定类别,POSIX表示目前较新类型的文件锁,由lockf系统调用产生,FLOCK是传统的UNIX文件锁,由flock系统调用产生;第三列也通常由两种类型,ADVISORY表示不允许其他用户锁定此文件,但允许读取,MANDATORY表示此文件锁定期间不允许其他用户任何形式的访问; 
  • /proc/mdstat  保存RAID相关的多块磁盘的当前状态信息,在没有使用RAID机器上,其显示为如下状态: 
  • /proc/meminfo  系统中关于当前内存的利用状况等的信息,常由free命令使用;可以使用文件查看命令直接读取此文件,其内容显示为两列,前者为统计属性,后者为对应的值; 
  • /proc/mounts  在内核2.4.29版本以前,此文件的内容为系统当前挂载的所有文件系统,在2.4.19以后的内核中引进了每个进程使用独立挂载名称空间的方式,此文件则随之变成了指向/proc/self/mounts(每个进程自身挂载名称空间中的所有挂载点列表)文件的符号链接;/proc/self是一个独特的目录,后文中会对此目录进行介绍; 
  • /proc/modules  当前装入内核的所有模块名称列表,可以由lsmod命令使用,也可以直接查看;如下所示,其中第一列表示模块名,第二列表示此模块占用内存空间大小,第三列表示此模块有多少实例被装入,第四列表示此模块依赖于其它哪些模块,第五列表示此模块的装载状态(Live:已经装入;Loading:正在装入;Unloading:正在卸载),第六列表示此模块在内核内存(kernel memory)中的偏移量; 
  • /proc/partitions  块设备每个分区的主设备号(major)和次设备号(minor)等信息,同时包括每个分区所包含的块(block)数目(如下面输出中第三列所示); 
  • /proc/pci  内核初始化时发现的所有PCI设备及其配置信息列表,其配置信息多为某PCI设备相关IRQ信息,可读性不高,可以用“/sbin/lspci –vb”命令获得较易理解的相关信息;在2.6内核以后,此文件已为/proc/bus/pci目录及其下的文件代替; 
  • /proc/slabinfo  在内核中频繁使用的对象(如inode、dentry等)都有自己的cache,即slab pool,而/proc/slabinfo文件列出了这些对象相关slap的信息;详情可以参见内核文档中slapinfo的手册页; 
  • /proc/stat     实时追踪自系统上次启动以来的多种统计信息;如下所示,其中, 
    “cpu”行后的八个值分别表示以1/100(jiffies)秒为单位的统计值(包括系统运行于用户模式、低优先级用户模式,运系统模式、空闲模式、I/O等待模式的时间等); 
    “intr”行给出中断的信息,第一个为自系统启动以来,发生的所有的中断的次数;然后每个数对应一个特定的中断自系统启动以来所发生的次数; 
    “ctxt”给出了自系统启动以来CPU发生的上下文交换的次数。 
    “btime”给出了从系统启动到现在为止的时间,单位为秒; 
    “processes (total_forks) 自系统启动以来所创建的任务的个数目; 
    “procs_running”:当前运行队列的任务的数目; 
    “procs_blocked”:当前被阻塞的任务的数目; 
  • /proc/swaps  当前系统上的交换分区及其空间利用信息,如果有多个交换分区的话,则会每个交换分区的信息分别存储于/proc/swap目录中的单独文件中,而其优先级数字越低,被使用到的可能性越大;下面是作者系统中只有一个交换分区时的输出信息; 
  • /proc/uptime  系统上次启动以来的运行时间,如下所示,其第一个数字表示系统运行时间,第二个数字表示系统空闲时间,单位是秒; 
  • /proc/version  当前系统运行的内核版本号。
  • /proc/vmstat  当前系统虚拟内存的多种统计数据,信息量可能会比较大,这因系统而有所不同,可读性较好;下面为作者机器上输出信息的一个片段;(2.6以后的内核支持此文件) 
  • /proc/zoneinfo  内存区域(zone)的详细信息列表,信息量较大,

 

进程文件夹 ( /proc/数字文件夹/ )

随便进入一个 进程文件夹,通过 进程文件夹 下的 文件就可以查看 进程在内存中对应的信息

  • cmdline — 启动当前进程的完整命令,但僵尸进程目录中的此文件不包含任何信息; 
  • cwd — 指向当前进程运行目录的一个符号链接; 
  • environ — 当前进程的环境变量列表,彼此间用空字符(NULL)隔开;变量用大写字母表示,其值用小写字母表示; 
  • exe — 指向启动当前进程的可执行文件(完整路径)的符号链接,通过 /proc/N/exe 可以启动当前进程的一个拷贝; 
  • fd — 这是个目录,包含当前进程打开的每一个文件的文件描述符(file descriptor),这些文件描述符是指向实际文件的一个符号链接; 
  • limits — 当前进程所使用的每一个受限资源的软限制、硬限制和管理单元;此文件仅可由实际启动当前进程的UID用户读取;(2.6.24以后的内核版本支持此功能); 
  • maps — 当前进程关联到的每个可执行文件和库文件在内存中的映射区域及其访问权限所组成的列表; 
  • mem — 当前进程所占用的内存空间,由 open、read 和 lseek 等系统调用使用,不能被用户读取; 
  • root — 指向当前进程运行根目录的符号链接;在Unix和Linux系统上,通常采用chroot命令使每个进程运行于独立的根目录; 
  • stat — 当前进程的状态信息,包含一系统格式化后的数据列,可读性差,通常由 ps 命令使用; 
  • statm — 当前进程占用内存的状态信息,通常以“页面”(page)表示; 
  • status — 与 stat 所提供信息类似,但可读性较好,如下所示,每行表示一个属性信息;其详细介绍请参见 proc的man手册页; 
  • task — 目录文件,包含由当前进程所运行的每一个线程的相关信息,每个线程的相关信息文件均保存在一个由线程号(tid)命名的目录中,这类似于其内容类似于每个进程目录中的内容;(内核2.6版本以后支持此功能) 

 

/dev 目录

设备文件分为两种:块设备文件(b) 和 字符设备文件(c)

设备文件一般存放在/dev目录下,对常见设备文件作如下说明:

目录

描述

/dev/hd[a-t]

IDE设备

/dev/sd[a-z]

SCSI设备

/dev/fd[0-7]

标准软驱

/dev/md[0-31]

软raid设备

/dev/loop[0-7]

本地回环设备

/dev/ram[0-15]

内存

/dev/null

无限数据接收设备,相当于黑洞

/dev/zero

无限零资源

/dev/tty[0-63]

虚拟终端

/dev/ttyS[0-3]

串口

/dev/lp[0-3]

并口

/dev/console

控制台

/dev/fb[0-31]

framebuffer

/dev/cdrom

=> /dev/hdc

/dev/modem

=> /dev/ttyS[0-9]

/dev/pilot

=> /dev/ttyS[0-9]

/dev/random

随机数设备

/dev/urandom

随机数设备

 

 

 

 

 

  • 7
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值