zoukankan      html  css  js  c++  java
  • linux基础之磁盘管理与文件系统

    上面一篇文章(https://www.cnblogs.com/ckh2014/p/7224851.html)介绍了硬盘的基本结构,那么一块磁盘如何应用取存储数据呢?

    它的步骤是这样的: 

    识别硬盘 --> 磁盘分区 --> 分区格式化 --> 挂载 --> 写入/存储数据

    识别硬盘

    这是linux内核的事情,在之前博文CentOS启动流程(https://www.cnblogs.com/ckh2014/p/9571066.html)中介绍系统启动时内核会初始化加载硬盘的驱动程序,所以我们登录系统后fdisk会查看到硬盘的相关信息。

     磁盘分区

    分区模式有MBR和GPT两种模式:

    MBR:Master Boot Record,主引导记录模式,也称为MSDOS模式
    MBR模式是在硬盘的第一个扇区(512bytes)中,将前446bytes用来记录引导程序,后面64bytes用来记录分区表(partition table),最后2bytes为结束符号。
    分区表(64bytes)中每16个bytes标识一个分区,所以只能标识四个主分区,存储容量最大约2.2TB
    GPT:GUID Partition table,全局唯一标识磁盘分区表

    GPT模式打破了MBR的限制,可以设置多达128个分区,分区的大小根据操作系统的不同有所变化,但是都突破了2T空间的限制。支持高达 18EB (1EB=1024PB,1PB=1024TB) 的卷大小,允许将主磁盘分区表和备份磁盘分区表用于冗余,还支持唯一的磁盘和分区 ID (GUID)。

    与 MBR 分区的磁盘不同,GPT的分区信息是在分区中,而不象MBR一样在主引导扇区。为保护GPT不受MBR类磁盘管理软件的危害,GPT在主引导扇区建立了一个保护分区 (Protective MBR)的MBR分区表,这种分区的类型标识为0xEE,这个保护分区的大小在Windows下为128MB,Mac OS下为200MB,在Window磁盘管理器里名为GPT保护分区,可让MBR类磁盘管理软件把GPT看成一个未知格式的分区,而不是错误地当成一个未分区的磁盘。
    在MBR硬盘中,分区信息直接存储于主引导记录(MBR)中(主引导记录中还存储着系统的引导程序)。但在GPT硬盘中,分区表的位置信息储存在GPT头中。但出于兼容性考虑,硬盘的第一个扇区仍然用作MBR,之后才是GPT头。

    GPT使用34个LBA,最后33个用来做分区信息备份。
    逻辑区块位址中,LBA0(MBR相容区块)中446bytes用来存放开机管理程式(boot loader),原本用来存放分区表信息的地方只存放一个特殊标志,用来表示磁盘为GPT分区格式。
             LBA1(GPT表头记录)中记录了分区表的位置和大小,同时记录了备份用的GPT分区存放位置。
              LBA2-33(实际记录分区信息处),每个LBA默认有4个分区,总共512bytes,每个分区信息用到128bytes,这之中除了识别码和相关记录外,会有64bits来记录开始/结束的磁区号码。

    分区格式化

    硬盘分区后,如果想要实现对文件的快速存取以及访问,还要依赖文件系统,需要在分区上面创建文件系统。文件系统是一个软件,此处以ext文件系统为。文件储存在硬盘上,硬盘的最小存储单位叫扇区(Sector)。每个扇区储存512字节(相当于0.5KB)。操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个块(block)。这种由多个扇区组成的块是文件存取的最小单位,块的大小,最常见的是4KB,即连续八个sector组成一个block,文件数据都储存在块中,而每个数据文件存在哪些块中,从哪个块开始,到哪个块结束,那么很明显,我们还必须找到一个地方储存文件的元信息,比如文件的创建者、文件的创建日期、文件的大小等等。这种储存元信息的区域叫做inode,中文译名为”索引节点”。

         

    每一个inode有一个全局唯一的ID(这里的全局指的是某个分区下,某分区下不同文件的inode号不可能相同,不同分区的inode号有可能相同),每个inode中存放了对应文件的inode号,文件类型、属主属组、权限、大小、时间、以及文件数据存储在哪些磁盘块等信息(元数据中没有当前文件的文件名,当前文件的文件名存放在父目录的数据块中),如果一个文件过大,那么他需要的块就会很多,inode中存储的对应块信息就会很多,但是如果文件很大,成千上万的块信息的存储空间就会很大,它可以利用指针,指向另一个更大的空间,存储这些块信息。

     inode详细结构示意图如下:

    文件系统格式化,也就是将分区分成多个块组,有些是超级块,后面的块组中有些会有超级块的备份。块组的详细示意图如下:

    超级块包含信息要比普通块组多一些,下面详细介绍下超级块包含的信息。

    超级块详细信息:

    1.引导块(boot sector):
       如果没有引导代码,这两个扇区内容为空,全部用0填充

     2. 超级块(Super Block): 
        这个块是用来保存该磁盘上所有的块组的信息,比如每一个块组从哪一个块开始,到哪一个块结束等信息,  
      还包括各种meta信息, 块大小, 每个块组包含块数, 总块数, 第一个块前保留块数, inode节点数, 每个块组的inode节点数, 卷名, 最后挂载时间, 挂载路径, 
      文件系统是否干净, 是否要调用一致性检查标识,空间inode节点和空闲块的记录信息等, 在分配inode节点和新块的时候使用。
      因此一旦超级块坏掉了,其他所有块组的信息都无法读取了,所以超级块有很多备份,存放于其他块组中,但使用时只使用块组0中的超级块,一旦坏了就从其他块组中找一个加以恢复。

    3. 块组描述表(Group Description Table)
        块组描述符表中包含了所有块组的描述信息,它存放的是块位图(Block Bitmap)和 inode位图(Inode Bitmap),即哪些块是已用的,哪些块是空闲的;哪些inode是已用的,哪些inode是空闲的,这样  的位图比整个磁盘的位图要小得多,故扫描效率会提高很多。而通过Inode表(Inode Table)就可以找到相应的磁盘块(Data Blocks)。组描述符和超级块在每个块组中都有一个备份, 但是激活了稀疏超级块特  征的情况除外。稀疏超级块即不是在所有块组中都存储超级块和组描述符的备份, 默认该策略被激活, 其策略类似当块组号是3,5,7的幂的块组才存副本。  
    4.数据块位图
      每个块对应一个bit, 只包含了本块组的信息。而文件系统创建的时候, 默认每个块组包含的块数跟每个块包含的bit数是一样的。
    而该位图表的块的起始位置会在组描述符表中指定, 大小则为块组中包含块数个bit。
    5.inode位图
      跟块位图类似, 通常情况他也只占用一个块。通常一个块组中的inode节点数会小于block数量。
    6.inode节点表
      每个inode都占用128位的一个描述信息, 起始位置在组描述符表中表示。
    7.数据区
      这就是真正存储数据的区域。

    inode详细信息:

    上面提到inode表是存放每个文件元数据信息的,每一条元数据用一个inode表示,inode结构示意图如下

    这里介绍下块指针的概念

    直接块指针:
        12个直接指针,直接指向存储数据的块。假设一个block块大小为4k,那么直接块指针指向的块的大小总和为4k*12 = 48k,也就是说如果一个文件的数据大小不超过48k,
       使用直接块指针指向的块就能满足数据存储的需求。 间接块指针: 
       如果一个文件的大小大于48k,'直接块指针'指向的块大小无法满足存储需求,这时候就会用到‘间接块指针’,‘间接块指针’指向一个数据块,我们暂且称这个被‘间接块指针’指向的块为‘间接块’,
       ‘间接块’中不存放数据,而是存放指针,这些存放在‘间接块’中的指针再指向真正存放数据的块,我们还按照上述假设,每个块4k大小,
       假设每个指针占用4个字节的空间,那么一个4k的块能存放1024个指针,也就是间接块中能存放1024个指针,这些指针每个再指向一个4k的块,
       那么所有能指向的块的大小为4k * 1024 = 4M ,也就是说能够存放小于4M大小的文件。
    双重间接块指针: 同理,如果文件大于4M,‘间接块指针’能够指向的所有块的大小总和无法满足要求,这时候就会用到 ‘双重间接块指针’ ,‘双重间接块指针’的原理跟‘间接块指针’的原理相同,
       只是又多间接了一层,‘双重间接块指针’先指向一个‘间接块’,这个间接块里存放了1024个指针,‘间接块’里的每个指针再指向一个‘二重间接块’,因为每个块的大小都是4k
       所以每一个‘二重间接块’又能分化出1024个指针,这些来自‘二重间接块’的指针再指向真正存放数据的块。所以,总共算下来,能够存放1024 * 1024 * 4k = 4G 的数据。
    三重间接块指针: 三重间接块指针的原理同上,以此类推。三级指针可以储存文件数据大小为1024*1024*1024*4=4TB

    Linux中cp、rm、mv 、ln对inode的影响:

     cp命令

    •         分配一个未被使用的inode号,在inode表中添加一个新项目,(注意:如果是cp文件到已经存在的文件,则inode号采用被覆盖之前的目标文件的inode号)

    •         在目录中新建一个目录项,并指向步骤1中的inode

    •         把数据复制到block中

        rm命令

    •         减少链接数量,如果链接数为0,释放inode(inode号被重新使用);

    •         如果inode被释放,则数据块放到可用空间列表中;

    •         删除目录中的目录项

        mv命令

           1. 如果mv命令的目标文件和源文件所在的文件系统相同:

            使用新文件名建立目录项;

            删除带有原来文件名的目录项;

            注意:该操作对inode表没有影响(除时间戳),对数据的位置也没有影响,不移动任何数据。(即使是mv到一个已经存在的目标文件,新目录指向源文件inode,会先删除目标文件的目录项)

           2. 如果目标文件和源文件所在的文件系统不相同,就是cp和rm;

        ln命令

            符号(软)链接:

            符号链接的内容是它引用文件的名称,可以是任意文件或目录,也可以链接不同文件系统的文件,甚至可以链接不存在的文件,这就产生一般称为断裂的问题,还可以不断的循环链接源文,但是其大小为指向的路径字符串的长度;不增加或减少目标文件inode 的引用计数。

            使用ln -s source_file softlink_file (注意:源文件(source_file)的路径是相对路径(也可以是绝对路径,通常使用的是相对路径),一定是相对于软链接文件的路径,而非相对于当前工作目录的路径)创建符号链接,在对符号链接进行读写操作的时候,系统会自动把该操作转换为对源文件的操作,但是删除链接文件时,系统仅仅删除符号链接文件,而不是删除源文件本身。

        硬链接:

            不允许给目录创建硬链接,创建硬链接会增加inode的引用计数(不能跨驱动或分区创建硬链接),硬链接件对应于同一文件系统上的一个物理文件,硬链接节点编号是相同的,创建硬链接链接数递增,删除文件时:rm命令递减计数的链接,文件如果存在,至少有一个链接数,当链接数为0时,该文件被删除。

            使用ln existfile newfile 命令创建硬链接

            硬链接于软连接的区别:

            1、本质不同:硬链接是指向同一个文件,软链接指向的不是同一个文件

            2、删除时:硬链接不受影响,软链接失效

            3、创建链接时:创建硬链接链接数加1,创建软链接连接数不变

            4、是否可以跨分区:硬链接不可以跨分区,软链接可以跨分区

            5、目录是否可以创建链接:硬链接不可以对目录创建,软链接可以对目录创建

            6、硬链接的inode号相同,软链接inode号不同

    挂载

    Linux中的根目录以外的文件要想被访问,需要将其“关联”到根目录下的某个目录来实现,这种关联操作就是“挂载”,这个目录就是“挂载点”,解除关联关系的过程称之为“卸载”。

      注意:“挂载点”的目录需要以下几个要求:

        (1)目录事先存在,可以用mkdir命令新建目录;

        (2)挂载点目录不可被其他进程使用到;

        (3)挂载点下原有文件将被隐藏。

    最后介绍下磁盘管理和文件系统的相关命令:

    1.分区相关的命令

    对硬盘分区:只能管理15个分区  

      # fdisk -l  //显示当前系统上所有的磁盘分区情况
      # fdisk DEVICE: //对某个设备分区,比如硬盘sdb
         自命令:管理功能
            p:  print,显示已有分区
            n: new,创建一个分区
            d: delete, 删除一个分区
            t: 调整分区id
            l: 列表显示分区id
            w: write: 写入磁盘并退出
            q:quit, 放弃更新并退出            

    通过上面的命令创建好分区后,需要重新读取硬盘分区表

    有三种命令可以实现:
       1. partx -a /dev/device        -n M:N 读取哪几个分区
       2. kpartx -a /dev/device        -f: force
       3. partprobe [/dev/device]

    查看内核是否已经识别新分区 

    cat /proc/partitions
    有些时候重新读取新分区后,旧的已经删除的分区还在,这时可通过 partprobe重新读取分区信息,会删除旧的记录。

    2、文件系统格式化相关命令

    mkfs命令:
        # mkfs.FS_TYPE /dev/DEVICE
        # mkfs -t FS_TYPE /dev/DEVICE         -l 'LABEL': //设定卷标
            FS_TYPE文件系统类型有 ext2、ext3、ext4、xfs、btrfs、vfat
    mke2fs: ext系列文件系统专用管理工具
          -t {ext2 | ext3 | ext4}  // 文件系统类型
          -b {1024 | 2048 | 4096}  // 块大小
          -L 'LABEL'    // 设定卷标
          -j: 相当于 -t ext3    // 开启日志功能
          -i   #:   // 为数据空间中每多少个字节创建inode
          -N # :   // 为数据空间创建多少个inode
          -m # :   // 为管理人员预留的空间占用的百分比,默认为百分之5
          -O FEATURE[...]:   // 启用指定特性
          -O ^FEATURE:   // 关闭指定特性
    mkswap: 创建交换分区       -L 'LABEL'
    blkid: 块设备属性信息查看
          -U UUID: 根据指定的UUID来查找对应的设备
          -L LABEL: 根据指定的LABEL来查找对应的设备
    e2label: 管理ext系列文件系统的LABEL
       #e2label DEVICE [LABEL]
    tune2fs: 重新设置ext系列文件系统可调整参数的值
          -l: 查看指定文件系统超级块信息
          -L 'LABEL':修改LABEL
          -m #: 修改预留给管理员的空间百分比
          -j: ext2升级为ext3
          -O: 文件系统属性启用或禁用
          -o: 调整文件系统的默认挂载选项
          -U UUID:修改UUID号
    dumpe2fs:  // 查看卷组信息
          -h: 查看超级块信息
    文件系统检测:
          fsck.FS_TYPE
          fsck -t FS_TYPE
            -a: 自动修复错误
            -r: 交互式修复错误
    
          e2fsck: ext系列文件专用的检测修复工具
            -y: 自动回答yes
            -f: 强制修复

    3. 挂载与卸载相关命令

    挂载命令:mount

    卸载命令: umount

    挂载命令:mount

      mount命令: 通过查看/etc/mtab文件显示当前系统已挂载的所有设备

      查看内核追踪到的已挂载的所有设备: cat /proc/mounts

      mount [-fnrsvw] [-t vfstype] [-o options] device dir  //注意: 挂载点下原有文件在挂载完成后会被临时隐藏  

        device:指明要挂载的设备
          (1)设备文件:例如:/dev/sda5
          (2)卷标:-L 'LABEL' 例如 -L "MYDATA"
           (3) UUID,-U 'UUID' 例如 -U 'ABD12ds12'
          (4)伪文件系统名称:proc,sysfs,devtmpfs,configfs
        dir:挂载点
          事先存在:建议使用空目录:
          进程正在使用中的设备无法被卸载(/application/htdocs)

        常用选项:
          -t vfstype: 指定要挂载的设备上的文件系统类型
          -r: readonly,只读挂载
          -w: read and write,读写挂载
          -n: 不更新/etc/mtab
          -a: 自动挂载所有支持自动挂载的设备:(定义在了 /etc/fstab文件中,且挂载选项中有“自动挂载”功能)
          -U 'UUID': 以UUID指定要挂载的设备
          -B,--bind: 绑定目录到另一个目录上

        -o options: (挂载文件系统的选项)
            async: 异步模式:
            sync: 同步模式:
            atime/noatime:
            diratime/nodiratime:目录的访问时间戳
            auto/noauto: 是否支持自动挂载
            exec/noexec:是否支持将文件系统上应用程序运行为进程
            dev/nodev: 是否支持在此文件系统上使用设备文件
            suid/nosuid:
            remount:重新挂载
            ro:
            rw:
            user/nouser:是否运行普通用户挂载此设备
            acl: 启用此文件系统上的acl功能

      注意:上述选项可多个同时使用,彼此使用逗号分隔
      默认挂载选项:defaults(rw,suid,dev,exec,auto,nouser,and async)

    卸载命令:umount DEVICE
    挂载交换分区:
          启用:swapon
             swapon [OPTION]...[DEVICE]
                -a: 激活所有的交换分区
                -p: PRIORITY:指定优先级
          禁用: swapoff [OPTION]...[DEVICE]
    查看正在访问指定文件系统的进程:
            fuser -v MOUNT_POINT
            fuer -km MOUNT_POINT  终止所有正在访问指定文件系统的进程
    内存空闲使用状态:
            free [OPTION]
              -m: 以MB为单位
              -g: 以GB为单位
    文件系统空间占用等信息的查看工具:
            df [OPTION]
              -h: human-readable
              -l: inodes instead of blocks
              -P: 以Posix兼容的格式输出
    查看某目录总体空间占用状态:
            du [OPTIONS] DIR
              -h: human-readable
              -s: summary

    要实现开机自动挂载,则要修改挂载的配置文件: /etc/fstab

    每行定义一个要挂载的文件系统:
          1.要挂载的设备或伪文件系统: 设备文件、LABEL(LABEL="")、UUID(UUID="")、伪文件系统名称(proc、sysfs) 
          2.挂载点
          3.文件系统类型
          4.挂载选项: defaults
          5.转储频率:
             0:不做备份
             1:每天转储
             2:每隔一天转储
          6.自检次序:
             0:不自检
             1:首先自检,一般只有rootfs才用1

    四、实例

    1.创建一个20G的文件系统,块大小为2048,文件系统为ext4,卷标为TEST,要求此分区开机后自动挂载至/testing目录,且默认有acl挂载选项
          a. 创建20G的分区
          b. mke2fs  -t ext4 -b 2048 -L TEST /dev/DEVICE
          c. 编辑/etc/fstab: 增加一行:LABEL="TEST" /testing ext4 defaults,acl 0 0 
    2.创建一个5G的文件系统,卷标HUGE,要求此分区开机自动挂载至/mogdata目录,文件系统类型为ext3
          a. 创建5G分区
          b. mkfs.ext3 -L HUGE /dev/DEVICE
          c. 修改配置文件/etc/fstab: 增加一行:LABEL='HUGE' /mogdata ext3 defaults 0 0 
    3.写一个脚本:
       (1)列出当前系统识别到的所有磁盘设备
        # fdisk -l | grep -o "^Disk /dev/[sh]d[a-z]"
       (2)如磁盘数量为1,则显示其空间使用信息,如果大于1则显示最后一条
        #!/bin/bash
        #
        disknum=$(fdisk -l | grep -o "^Disk /dev/[sh]d[a-z]" | wc -l)
        if [ $disknum -eq 1  ]: then
        fdisk -l `fdisk -l | grep -o "^Disk /dev/[sh]d[a-z]" | cut -d' ' -f2`
        else
          fdisk -l `fdisk -l | grep -o "^Disk /dev/[sh]d[a-z]" | tail -1 | cut -d' ' -f2 ` 
        fi       
  • 相关阅读:
    HDU 1402 A * B Problem Plus FFT
    HDU 4609 3-idiots FFT
    Hihocoder #1527 : 快速乘法 DP
    Codeforces Round #420 (Div. 2) E. Okabe and El Psy Kongroo DP+矩阵快速幂加速
    Codeforces 8VC Venture Cup 2016
    FFT做题记录
    Hackrank Candies DP
    git submodule update --init --recursive
    慢慢长大
    protobuf
  • 原文地址:https://www.cnblogs.com/ckh2014/p/10813097.html
Copyright © 2011-2022 走看看