每天学五分钟 Liunx 100 | 存储篇:磁盘分区
这一节主要介绍 Liunx 是怎么用磁盘的。
磁盘分区
在 Liunx 中一切皆文件,磁盘在 Liunx 中也是文件,包括 /dev/hd[a-d](以 IDE 为接口) 和 /dev/sd[a-p](以 SCSI/SATA/U盘) 等类型的磁盘设备文件名。
[root@test1 test]# ll /dev/ | grep sda
brw-rw----. 1 root disk 8, 0 Mar 12 22:45 sda
brw-rw----. 1 root disk 8, 0 Mar 12 22:45 sda1
brw-rw----. 1 root disk 8, 0 Mar 12 22:45 sda2
brw-rw----. 1 root disk 8, 0 Mar 12 22:45 sdb
(测试机1的磁盘设备文件名是 sda)
Liunx 开机启动的时候 BIOS 会读 CMOS 芯片里的参数,然后到 MBR(主引导分区)中执行引导加载程序,引导加载程序再读取内核文件从而启动操作系统。
这其中至关重要的 MBR 就放在磁盘的第一扇区。
第一扇区有 512 bytes,MBR 的大小是 446 bytes,还有 64 bytes 用来记录整块磁盘的分区表。由于每个分区需要 16 bytes 来记录,所以原则上只能记录 4 个分区。Liunx 引入扩展分区和逻辑分区的概念来解决这个问题。
如下图所示:
P1 是主分区,P2 是扩展分区,L1/L2/L7 是逻辑分区。其中,扩展分区的分区表是记录在非第一扇区中的。
它们对应的设备文件名是:
P1: /dev/sda1
P2: /dev/sda2
L1: /dev/sda5
L2: /dev/sda6
L3: /dev/sda7
sda1-sda4 是留给主分区和扩展分区用的,所以逻辑分区从 sda5 开始分配。
再看测试机1磁盘设备文件名为 /dev/sda,它有两个主分区 /dev/sda1 和 /dev/sda2,没有逻辑分区。
[root@test1 test]# ll /dev/ | grep sda
brw-rw----. 1 root disk 8, 0 Mar 12 22:45 sda
brw-rw----. 1 root disk 8, 1 Mar 12 22:45 sda1
brw-rw----. 1 root disk 8, 2 Mar 12 22:45 sda2
brw-rw----. 1 root disk 8, 0 Mar 12 22:45 sdb
磁盘设备 sdb 没有用到,通过 fdisk 命令在 sdb 上新增磁盘分区:
[root@test1 ~]# fdisk /dev/sdb
Welcome to fdisk (util-linux 2.23.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Device does not contain a recognized partition table
Building a new DOS disklabel with disk identifier 0xd2793837.
The device presents a logical sector size that is smaller than
the physical sector size. Aligning to a physical sector (or optimal
I/O) size boundary is recommended, or performance may be impacted.
Command (m for help): n
Partition type:
p primary (0 primary, 0 extended, 4 free)
e extended
Select (default p):
Using default response p
Partition number (1-4, default 1):
First sector (2048-1875385007, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-1875385007, default 1875385007):
Using default value 1875385007
Partition 1 of type Linux and of size 894.3 GiB is set
Command (m for help): w
The partition table has been altered!
Calling ioctl() to re-read partition table.
Syncing disks.
[root@controller-0 sqg04]# partprobe
[root@controller-0 sqg04]# cd /dev/sd
sda sda1 sda2 sdb sdb1
现在 sdb 的主分区 sdb1 分出来了,记得分完区之后要用 partprobe 命令更新分区表,不然只能重启系统来更新分区表了。
文件系统
分完区的磁盘需要制成文件系统,才能成为 Liunx 可以使用的文件系统格式。
常见的文件系统类型有 ext2/ext3/ext4 和 nfs/gfs 等等。
通过 df 命令查看文件系统的信息:
# df -hT
Filesystem Type Size Used Avail Use% Mounted on
/dev/vda1 ext4 40G 4.7G 33G 13% /
tmpfs tmpfs 16G 20M 16G 1% /tmp
/dev/mapper/vol1-provider_ccs ext4 4.6G 22M 4.3G 1% /mnt/bricks/ccs
tmpfs tmpfs 294M 267M 28M 91% /mnt/rcpha/image
/dev/loop0 ext4 277M 125M 134M 49% /mnt/rcpha/etcd
example-5gbts-04-OAM-000.local:/mstate nfs4 477M 77M 371M 18% /mnt/mstate
sct-20a-12345678-oam-000.local:/services fuse.glusterfs 1.8G 234M 1.4G 15% /mnt/services
(测试机 2 有四种类型的文件系统:ext4/tmpfs/nfs4/fuse.glusterfs)
每种文件系统都有自己的“特色”。以 ext 系列文件系统举例,其示意图如下:
inode:记录文件的属性,一个文件占用一个 inode,同时记录此文件数据所在的 block 号码。
block:实际记录文件的内容,若文件太大时会占用多个 block。
启动扇区: 启动扇区中可以安装引导装载程序。
blockgroup:文件系统中的 inode 和 block 太多,不易管理。因此,将文件系统划分成多个 block group。每个 group 都是一个小“文件系统”,有独立的 inode 和 block,superblock 。
superblock:记录整个文件系统的信息,包括 inode / block 的总量/使用量/剩余量,以及文件系统的格式等信息。superblock 一般只会在第一个 group 有,在其它 group 如果有,则为此 block 的备份。
文件系统描述: 说明每个 block group 的开始和结束 block 号码,以及每个 block 区段分别介于哪个 block 之间。
块对应表: 记录使用与未使用的 block 号码。这样系统就知道哪块 block 没用到,可以把文件存在尚未使用到的 block 。
inode 对应表:和块对应表类似,记录使用与未使用的 inode 号码。
inode table:记录文件的属性和 block 的号码。文件的属性包括该文件的访问模式(r/w/x),文件的所有者与组,文件的大小,文件的创建时间等等。block 号码则是该文件存放在哪块 block 里,可以根据 inode table 的记录访问该文件的内容。
data block:存放文件的数据,一个 block 只能存放一个文件的数据。block 的大小有 1K/2K/4K 三种,如果存放的数据过小于 block 的大小则造成 block 的浪费,如果存放的数据大于 block 的大小即需要多个 block 来存放文件。
通过 mkfs 命令将磁盘分区 sdb1 制成文件系统,其中 -t 选项指定文件系统类型:
[root@test1 ~]# mkfs -t ext4 /dev/sdb1
mke2fs 1.42.9 (28-Dec-2013)
Discarding device blocks: done
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
58613760 inodes, 234422870 blocks
11721143 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=2382364672
7155 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
102400000, 214990848
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done
挂载点
文件系统做好之后,用户还是无法使用。因为 Liunx 中一切皆文件,做好的文件系统并不能用文件的形式呈现给用户,供用户使用。所以需要对文件系统进行挂载,挂载就是提供用户一个目录入口,通过该目录入口来访问文件系统。
通过 mount 命令进行挂载。首先创建挂载目录,目录最好是空的,如果不是空的,挂载上的文件系统会把原来目录文件的内容隐藏掉。然后将文件系统 /dev/sdb1 挂载到该目录:
[root@test1 home]# df -hT
Filesystem Type Size Used Avail Use% Mounted on
/dev/sda2 xfs 895G 848G 47G 95% /
[root@test1 home]# mount /dev/sdb1 /home/test
[root@test1 home]# df -hT
Filesystem Type Size Used Avail Use% Mounted on
/dev/sda2 xfs 895G 848G 47G 95% /
/dev/sdb1 ext4 881G 77M 836G 1% /home/test
现在可以通过读写 /home/test 目录来访问文件系统,从而实现在磁盘中存取数据。
文件系统实例
通过 dumpe2fs 命令查看 ext 系列文件系统的内容:
[root@test2:/home/robot]
# dumpe2fs /dev/vda1
dumpe2fs 1.45.5 (07-Jan-2020)
Filesystem volume name: rootfs # 文件系统的名称(Label)
Last mounted on: /sysroot
Filesystem UUID: 18b9201d-3a23-4c98-ab26-7b52c342da23
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal ext_attr resize_inode dir_index filetype needs_recovery extent 64bit flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl
Filesystem state: clean # 文件系统的状态没问题
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 2621440 # 总的 inode 数目
Block count: 10485499 # 总的 block 数目
Reserved block count: 450842
Free blocks: 9018609
Free inodes: 2580673
First block: 0
Block size: 4096
Fragment size: 4096
Group descriptor size: 64
Reserved GDT blocks: 763
Blocks per group: 32768 # 每个 group 有多少个 block
Fragments per group: 32768
Inodes per group: 8192
Inode blocks per group: 512 # 每个 group 有多少个 inode
Flex block group size: 16
Filesystem created: Wed Feb 12 16:09:19 2020
Last mount time: Fri Mar 13 14:25:56 2020
Last write time: Fri Mar 13 14:25:56 2020
Mount count: 8
Maximum mount count: -1
Last checked: Thu Feb 13 09:58:45 2020
Check interval: 0 (<none>)
Lifetime writes: 12 GB
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 256
Required extra isize: 32
Desired extra isize: 32
Journal inode: 8
First orphan inode: 262571
Default directory hash: half_md4
Directory Hash Seed: 35426ac6-7885-4c68-9f84-f5d639422c77
Journal backup: inode blocks
Journal features: journal_incompat_revoke journal_64bit
Journal size: 64M
Journal length: 16384
Journal sequence: 0x00008261
Journal start: 5725
Group 0: (Blocks 0-32767) csum 0x2580 [ITABLE_ZEROED]
Primary superblock at 0, Group descriptors at 1-5 # superbock
Reserved GDT blocks at 6-768
Block bitmap at 769 (+769)
Inode bitmap at 785 (+785)
Inode table at 801-1312 (+801)
20030 free blocks, 808 free inodes, 878 directories
Free blocks: 9036-9759, 10152-10173, 10766, 10769, 10771-10773, 13489-32767
Free inodes: 264-783, 803, 1270-1289, 1326-1336, 1346-1361, 1381-1390, 1430-1468, 1619-1634, 1650-1662, 2408-2471, 2687-2713, 2741-2791, 2826-2834, 2868-2878
Group 1: (Blocks 32768-65535) csum 0x0061 [ITABLE_ZEROED]
Backup superblock at 32768, Group descriptors at 32769-32773 # backup superblock
Reserved GDT blocks at 32774-33536
Block bitmap at 770 (bg #0 + 770)
Inode bitmap at 786 (bg #0 + 786)
Inode table at 1313-1824 (bg #0 + 1313)
1971 free blocks, 2605 free inodes, 638 directories, 2374 unused inodes
Free blocks: 35584-35647, 35712-35791, 35812-35839, 35968-36031, 36120-36127, 36160-36163, 36234-36236, 36332-36543, 36573-36591, 36611, 36622-36635, 36725-36831, 36863, 36896-37375, 38010, 38020-38021, 38023-38034, 38037-38038, 38040-38046, 38048-38050, 38053-38911
Free inodes: 8380, 8425, 8749-8765, 8862-8864, 8867-8869, 8871-8872, 8874-8875, 8877-8912, 8968, 8971, 8974, 8996-9020, 9024-9047, 9049-9062, 9247, 9277-9294, 9823, 10168-10209, 10809-10811, 11341, 11395-11396, 13426-13428, 13436-13446, 13453, 13455, 13994-14009, 14011-16384
ls 的 -i 选项可以查看文件使用的 inode 号码:
[root@test1:/home/robot]
# touch fileSystem.log
[root@example-5gbts-04-OAM-000:/home/robot]
# ll -hi
total 0
524586 -rw-r--r-- 1 root root 0 Mar 15 11:03 fileSystem.log
(文件 fileSystem.log 的 inode 号码是 524586)
目录在文件系统中也由 inode 和 block 组成。
目录的 inode 记录着目录下文件的权限/所有者等信息,目录的 block 则记录着目录下文件/目录的 inode 号码。
通过 ls 的 -d 和 -i 选项可以查看目录的 inode 号码:
[root@test1:/home/robot]
# ll -di test/
656226 drwxr-xr-x 2 root root 4096 Mar 15 11:30 test/
(目录 test 的 inode 号码是 656226)
介绍 Liunx 中软链接和硬链接的概念以加深对 inode 和 block 的理解。
先用 ln 命令造出链接文件, -s 选项指定链接文件为软链接文件:
[root@test1:/home/robot/test]
# ll -di /home/robot/test/
656226 drwxr-xr-x 2 root root 4096 Mar 15 11:36 /home/robot/test/
[root@test1:/home/robot/test]
# ln -s fileSystem.log fileSystem_sln.log
[root@test1:/home/robot/test]
# ln fileSystem.log fileSystem_hln.log
[root@test1:/home/robot/test]
# ll -i
total 0
524586 -rw-r--r-- 2 root root 0 Mar 15 11:03 fileSystem_hln.log
524586 -rw-r--r-- 2 root root 0 Mar 15 11:03 fileSystem.log
656227 lrwxrwxrwx 1 root root 14 Mar 15 11:36 fileSystem_sln.log -> fileSystem.log
软链接:
软链接中,链接文件 fileSystem._sln.log 的 block 记录的是被链接文件的 inode,被链接文件的 block 记录的是真实数据的 inode 号码,根据该 inode 号码来指向真实的数据。所以删掉 fileSystem.log 文件,软链接文件会提示找不到文件。
硬链接:
硬链接中,链接文件 fileSystem_hln.log 的 block 记录的是真实数据的 inode 号码,被链接文件的 block 记录的也是真实数据的 inode 号码。所以删掉被链接文件 fileSystem.log 依然能够访问链接文件。
系统读取 fileSystem.log 文件过程:
[root@test1:/home/robot/test]
# ll -di / /home/ /home/robot/ /home/robot/test/
2 drwxr-sr-x 20 root root 4096 Mar 13 14:27 /
8197 drwxr-xr-x 5 root root 4096 Mar 13 14:27 /home/
524372 drwxr-xr-x 4 robot root 4096 Mar 15 11:36 /home/robot/
656226 drwxr-xr-x 2 root root 4096 Mar 15 11:36 /home/robot/test/
[root@test1:/home/robot/test]
# ll -hi
total 0
524586 -rw-r--r-- 2 root root 0 Mar 15 11:03 fileSystem_hln.log
524586 -rw-r--r-- 2 root root 0 Mar 15 11:03 fileSystem.log
656227 lrwxrwxrwx 1 root root 14 Mar 15 11:36 fileSystem_sln.log -> fileSystem.log
系统通过挂载点信息 /dev/vda1 读根目录 / 的 inode 号码 2。 其中,inode 记录着用户/用户组的权限。
系统判断用户具有读文件权限,继续读 / 的 block ,block 中记录的 home 目录的 inode 号码 8197。
读取 home 目录的 block 内容读到 robot 用户的 inode 号码 524372。
继续读取 robot 目录的 block 内容读到 test 目录的 inode 号码 656226。
读取 test 目录的 block,发现 block 中有文件 fileSystem_hln.log 的 inode 号码。
读取 fileSystem_hln.log 的 block 内容,从而获取到文件的内容。
(完)
芝兰生于空谷,不以无人而不芳。