【Linux】Ext2文件系统、软硬链接
Ext2文件系统
- 一.理解硬件
- 1.磁盘、服务器、机柜、机房
- 2.磁盘的物理结构
- 3.磁盘的存储结构
- 4.磁盘的逻辑结构
- 1.理解过程
- 2.真实过程
- 5.CHS地址、LBA地址转换
- 二.引入文件系统
- 1.引入"块"概念
- 2.引入"分区"概念
- 3.引入"inode"概念
- 三.Ext2文件系统
- 1.宏观认识
- 2.Block Group
- 1.Super Block
- 2.Group Descriptor Table
- 3.Block Bitmap、Inode Bitmap
- 4.Inode Table、Data Block
- 3.inode 和 Data Block映射
- 4.inode 与文件名、目录
- 5.路径解析
- 6.路径缓存
- 7.挂载分区
- 8.文件系统总结
- 四.软硬链接
- 1.软链接
- 2.硬链接
本节重点:
- 理解磁盘物理结构。
- 掌握CHS地址和LBA地址。
- 掌握Ext系列文件系统原理。
- 理解分区,格式化,路径解析,挂载等过程和操作。
- 理解软硬连接使用和用途。
一.理解硬件
1.磁盘、服务器、机柜、机房
- 机械磁盘虽然在读写速度等方面不如固态硬盘,但凭借其大容量和低成本的优势,在很多领域仍有广泛的应用:大规模数据存储(机房)。笔记本主要使用的是固态硬盘。
- 计算机只认二进制,不同的硬件对于二进制的处理是不一样的。例如:磁盘可以看作由无数的磁铁组成,磁铁的南北极可以当做二进制01。
2.磁盘的物理结构
3.磁盘的存储结构
扇区:是磁盘存储数据的基本单位,512字节,块设备。修改磁盘中的数据本质是修改一/多的扇区,即便是1个byte的数据,也需要将整个扇区加载到内存中,修改后刷新到磁盘中(修改整个扇区),所以磁盘叫做块设备。而键盘与显示器是以字符为基本单位,叫做字符设备。
- 磁头摆动的本质:定位磁道(柱面)
- 磁盘盘片旋转的本质:定位扇区。
- 读写哪一个磁头的本质:读写哪一面。
CHS地址定位某个扇区:
- 可以先定位磁头(header)
- 确定磁头要访问哪一个柱面(磁道)(cylinder)
- 定位一个扇区(sector)
文件 = 内容 + 属性。都是数据,无非就是占据哪几个扇区的问题!能定位一个扇区了,就能定位多个扇区。
- 扇区是从磁盘读出和写入信息的最小单位,通常大小为 512 字节。
- 磁头(head)数:每个盘片一般有上下两面,分别对应1个磁头,共2个磁头。
- 磁道(track)数:磁道是从盘片外圈往内圈编号0磁道,1磁道…,靠近主轴的同心圆用于停靠磁头,不存储数据。
- 柱面(cylinder)数:磁道构成柱面,数量上等同于磁道个数。
- 扇区(sector)数:每个磁道都被切分成很多扇形区域,每道的扇区数量相同。
- 圆盘(platter)数:就是盘片的数量。
- 磁盘容量 = 磁头数 × 磁道(柱面)数 × 每道扇区数 × 每扇区字节数。
- 细节:传动臂上的磁头是共进退的。
柱面(cylinder),磁头(head),扇区(sector),显然可以定位数据了,这就是数据定位(寻址)方式之一,CHS寻址方式。
4.磁盘的逻辑结构
1.理解过程
磁带上面可以存储数据,我们可以把磁带 “拉直”,形成线性结构。
磁盘本质上虽然是硬质的,但是逻辑上我们可以把磁盘想象成为卷在一起的磁带,那么磁盘的逻辑存储结构我们也可以类似于:
这样每一个扇区,就有了一个线性地址(其实就是数组下标),这种地址叫做LBA。
2.真实过程
注意:传动臂上的磁头是共进退的。
柱面是一个逻辑上的概念,其实就是每一面上,相同半径的磁道逻辑上构成柱面。所以,磁盘物理上分了很多面,但是在我们看来,逻辑上磁盘整体是由 “柱面” 卷起来的。所以,磁盘的真实情况如下:
磁道:
柱面:
磁盘:
整个磁盘不就是多张二维的扇区数组表(三维数组)。所以寻址一个扇区时:先找到哪一个柱面(Cylinder),再确定柱面内哪一个磁道(磁头Head位置),最后确定扇区(Sector),所以就有了CHS。
我们之前学过C/C++的数组,在我们看来,其实全部都是一维数组:
所以,每一个扇区都有一个下标,我们叫做LBA(Logical Block Address)地址,其实就是线性地址。OS只用LBA地址,磁盘只用CHS地址!LBA地址转成CHS地址,CHS地址转换成为LBA地址,由磁盘自己来做!固件(硬件电路,伺服系统)
5.CHS地址、LBA地址转换
所以:在磁盘使用者看来,根本就不关心CHS地址,而是直接使用LBA地址,磁盘内部自己转换。
所以:从现在开始,磁盘就是一个以扇区为单位的一维数组,数组的下标就是每一个扇区的LBA地址。OS使用磁盘,就可以用一个数字访问磁盘扇区了。
二.引入文件系统
1.引入"块"概念
其实硬盘是典型的 “块” 设备,操作系统读取硬盘数据的时候,其实是不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个 “块” 。
硬盘的每个分区是被划分为一个个的 “块”。一个 “块” 的大小是由格式化的时候确定的,并且不可以更改,最常见的是4KB,即连续八个扇区组成一个 “块”。 “块” 是文件存取的最小单位。
注意:
- 磁盘就是一个三维数组,我们把它看待成为一个 “一维数组”,数组下标就是LBA,每个元素都是扇区。
- 每个扇区都有LBA,那么8个扇区一个块,每一个块的地址我们也能算出来。
- 知道LBA:块号 = LBA/8
- 知道块号:LAB = 块号*8 + n (n是块内第几个扇区)
2.引入"分区"概念
其实磁盘是可以被分成多个分区的,以Windows观点来看,你可能会有一块磁盘并且将它分区成C,D,E盘。那个C,D,E就是分区。分区从实质上说就是对硬盘的一种格式化。但是Linux的设备都是以文件形式存在,那是怎么分区的呢?
柱面是分区的最小单位,我们可以利用参考柱面号码的方式来进行分区,其本质就是设置每个区的起始柱面和结束柱面号码。此时我们可以将硬盘上的柱面(分区)进行平铺,将其想象成一个大的平面,如下图所示:
3.引入"inode"概念
到这我们要思考一个问题,文件数据都储存在 “块” 中,那么很显然,我们还必须找到一个地方储存文件的元信息(属性信息),比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode,中文译名为 “索引节点”。
每一个文件都有对应的inode,里面包含了与该文件有关的一些信息。为了能解释清楚inode,我们需要是深入了解一下文件系统。
所以一个文件的属性 inode 长什么样子呢?
struct ext2_inode
{
//截取了部分属性
__le16 i_mode; /* File mode */
__le16 i_uid; /* Low 16 bits of Owner Uid */
__le32 i_size; /* Size in bytes */
__le32 i_atime; /* Access time */
__le32 i_ctime; /* Creation time */
__le32 i_mtime; /* Modification time */
__le32 i_dtime; /* Deletion Time */
__le16 i_gid; /* Low 16 bits of Group Id */
__le16 i_links_count; /* Links count */
__le32 i_blocks; /* Blocks count */
__le32 i_flags; /* File flags */
//备注: EXT2_N_BLOCKS = 15
__le32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
};
还有两个问题:
- 我们已经知道硬盘是典型的"块"设备,操作系统读取硬盘数据的时候,读取的基本单位是"块"。"块"又是硬盘的每个分区下的结构,难道"块"是随意的在分区上排布的吗?那要怎么找到"块"呢?
- 还有就是上面提到的存储文件属性的inode,又是如何放置的呢?文件系统就是为了组织管理这些的!
三.Ext2文件系统
1.宏观认识
所有的准备工作都已经做完,是时候认识下文件系统了。我们想要在硬盘上存储文件,必须先把硬盘格式化为某种格式的文件系统,才能存储文件。文件系统的目的就是组织和管理硬盘中的文件。在Linux系统中,最常见的是 ext2 系列的文件系统。其早期版本为 ext2,后来又发出 ext3 和 ext4。ext3 和 ext4 虽然对 ext2 进行了增强,但是其核心设计并没有发生变化,我们仍是以较老的 ext2 作为演示对象。
ext2 文件系统将整个分区划分成若干个同样大小的块组(Block Group),如下图所示。只要能管理一个分区就能管理所有分区,也就能管理所有磁盘文件,分治思想。
上图中启动块(Boot Block/Sector)的大小是确定的,为1KB,由PC标准规定,用来存储磁盘分区信息和启动信息,任何文件系统都不能修改启动块。启动块之后才是 ext2 文件系统的开始。
2.Block Group
ext2 文件系统会根据分区的大小划分为数个Block Group。而每个Block Group都有着相同的结构组成。如下图所示:
1.Super Block
存放文件系统本身的结构信息,描述整个分区的文件系统信息。记录的信息主要有:bolck 和 inode 的总量,未使用的 block 和 inode 的数量,一个 block 和 inode 的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其它文件系统的相关信息。Super Block 的信息被破坏,可以说整个文件系统结构就被破坏了。
超级块表示的就是文件系统,文件系统以分区为单位,不同的分区可以是不同的文件系统。超级块在每个块组的开头都有以份拷贝(第一个块组必须有,后面的块组可以没有)。为了保证文件系统在磁盘部分扇区出现物理问题的情况下还能正常工作,就必须保证文件系统的 super block 信息在这种情况下也能正常访问。所以一个文件系统的 super block 会在多个 block group 中进行备份,这些 super block 区域的数据保持一致。
struct ext2_super_block
{
//截取了某些属性
__le32 s_inodes_count; /* 文件系统中 inode 的总数 */
__le32 s_blocks_count; /* 文件系统中数据块的总数 */
__le32 s_free_blocks_count; /* 文件系统中可用的空闲数据块数量 */
__le32 s_free_inodes_count; /* 文件系统中可用的空闲 inode 数量 */
__le32 s_first_data_block; /* 文件系统中第一个数据块的编号 */
__le32 s_blocks_per_group; /* 每个块组中包含的数据块数量 */
__le32 s_inodes_per_group; /* 每个块组中包含的 inode 数量 */
};
2.Group Descriptor Table
块组描述符表,描述块组属性信息,整个分区分成多个块组就对应有多少个块组描述符。每个块组描
述符存储⼀个块组的描述信息,如在这个块组中从哪⾥开始是inodeTable,从哪⾥开始是Data
Blocks,空闲的inode和数据块还有多少个等等。块组描述符在每个块组的开头都有⼀份拷⻉。
struct ext2_group_desc
{
__le32 bg_block_bitmap; /* Blocks bitmap block */
__le32 bg_inode_bitmap; /* Inodes bitmap */
__le32 bg_inode_table; /* Inodes table block*/
__le16 bg_free_blocks_count; /* Free blocks count */
__le16 bg_free_inodes_count; /* Free inodes count */
__le16 bg_used_dirs_count; /* Directories count */
__le16 bg_pad;
__le32 bg_reserved[3];
};
3.Block Bitmap、Inode Bitmap
分区后,每一个分区都格式化写入新的文件系统。
Block Bitmap:记录着Data Blocks中哪个数据块已经被占用,哪个数据块没有被占用。
Inode Bitmap:记录着inode是否空闲可用。
即便是修改Inode Bitmap中的一个比特位,也需要将所在的整个"块"加载到内存中进行修改,后再刷新到磁盘中。
4.Inode Table、Data Block
Inode Table:
- 存放文件属性,如文件大小,拥有者,最近修改时间等。
- 当前分组所有Inode属性的集合。
- inode编号以分区为单位整体划分,每一个分区都有自己的一套inode编号。inode编号可以跨组,但是不可跨分区。
- inode编号分配的时候,只需要确定每一个组的起始inode编号即可。
Data Block:
- 存放文件内容,也就是一个个的Block。
- 对于普通文件,文件的数据存储在数据块中。
- 对于目录,该目录下的所有文件名和目录名存储在所在目录的数据块中,除了文件名外,ls -l 命令看到的其它信息保存在该文件的inode中。
- Block号以分区为单位整体划分,每一个分区都有自己的一套Block号。Block号可以跨组,但是不可跨分区。
- Block号分配的时候,只需要确定每一个组的起始Block号即可。
操作系统任何管理文件系统?先描述,再组织!将Super Block和Group Descriptor Table以链表的形式管理起来,对文件系统的管理就是对链表的增删查改,所有的操作都是内存级的。
- 查找文件时:只需要知道文件的inode编号,根据每一个组的起始inode编号,先确定组的位置,再将该inode编号减去该组的起始inode编号,查找inode Bitmap,就能在inode Table中找到相应的inode,根据其中的映射关系,找到Block号,类似找Block。
- 删除文件时:先查找文件的inode,再将 Inode Bitmap 和 Block Bitmap 对应的比特位由1置为0。
- 恢复文件时:只需要知道文件的inode编号,并且将 Inode Bitmap 和 Block Bitmap 对应的比特位由0置为1。删除文件后想要恢复时,最好不要再次创建文件(可能会将删除文件的inode编号当做该新文件的inode),而是查看日志,找到删除文件的inode编号,交给专业的人去做。
- 修该文件时:先查找文件的inode,再将inode加载到内存和Block加载到文件内核级缓存区,修改后刷新到磁盘中。
- 新增文件时:先遍历Group Descriptor Table确定组,再遍历该组的inode Bitmap,获得局部的偏移量,最后根据该组的起始inode编号计算出当前的inode编号,返回给用户。
3.inode 和 Data Block映射
inode内部存在 __le32 i_block[EXT2_N_BLOCKS]; 其中EXT2_N_BLOCKS = 15,就是用来进行inode和block映射的。
4.inode 与文件名、目录
问题:
- 我们访问文件,都是用的文件名,没用过inode号啊?
- 目录是文件吗?如何理解?
答案:
- 目录也是文件,但是磁盘上没有目录的概念,只有文件属性+文件内容的概念。
- 目录的属性不用多说保存在inode中,内容保存的是:文件名和Inode号的映射关系,保存在Date Block中。
重新理解目录权限:
- 目录没有 r 权限时:无法查看目录中的文件内容,无法读取文件的inode和block。
- 目录没有 w 权限时:无法新建文件,无法将文件名和inode的映射关系写到目录的block中。
- 目录没有 x 权限时:无法进入该目录,无法打开该目录。
xzy@hcss-ecs-b3aa:~/code$ pwd
/home/xzy/code
xzy@hcss-ecs-b3aa:~/code$ ls -li
total 0
529852 -rw-rw-r-- 1 xzy xzy 0 Feb 13 17:38 Makefile
530295 -rw-rw-r-- 1 xzy xzy 0 Feb 13 17:38 test.c
529843 -rw-rw-r-- 1 xzy xzy 0 Feb 13 17:37 test.cpp
比如:要访问test.c,就必须打开test.c的工作目录,然后根据文件名test.c获得对应的inode,进而对文件进行访问。
5.路径解析
问题:打开当前工作目录文件,查看当前工作目录文件的内容?当前工作目录不也是文件吗?我们访问当前工作目录不也是只知道当前工作目录的文件名吗?要访问它,不也得知道当前工作目录的inode吗?
答案1:需要打开当前工作目录的上级目录,额…,上级目录不也是目录吗??不还是上面的问题吗?
答案2:所以类似"递归",需要把路径中所有的目录全部解析,出口是"/"根目录。
最终答案3:实际上任何文件,都有路径,访问目标文件,比如:/home/xzy/code/test.c。都要从根目录开始,依次打开每一个目录,根据目录名,依次访问每个目录下指定的目录,直到访问到test.c。这个从左向右的过程叫做Linux路径解析。
可是路径谁提供?
- 你访问文件,都是指令/工具访问,本质是进程访问,进程有CWD!进程提供路径,拼接后得到了完整路径。
可是最开始的路径从哪里来?
- 所以Linux为什么要有根目录,根目录下为什么要有那么多缺省目录?
- 你为什么要有家目录,你自己可以新建目录?
- 上面所有行为:本质就是在磁盘文件系统中,新建目录文件。而你新建的任何文件,都在你或者系统指定的目录下新建,这不就是天然就有路径了嘛!
- 系统+用户共同构建Linux路径结构。
6.路径缓存
问题1:Linux磁盘中,存在真正的目录吗?
答案:不存在,只有文件。只保存文件属性 + 文件内容。
问题2:访问任何文件,都要从根目录开始进行路径解析?
答案:原则上是,但是这样太慢,所以Linux会缓存历史路径结构。
问题3:Linux目录的概念,怎么产生的?
答案:打开的文件是目录的话,由OS自己在内存中进行路径维护。
Linux中,在内核中维护树状路径结构的内核结构体叫做: struct dentry
struct dentry
{
//截取了部分内容
atomic_t d_count;
unsigned int d_flags; /* protected by d_lock */
spinlock_t d_lock; /* per dentry lock */
struct inode *d_inode; /* Where the name belongs to - NULL is*/
struct hlist_node d_hash; /* lookup hash list */
struct dentry *d_parent; /* parent directory */
struct list_head d_lru; /* LRU list */
struct list_head d_subdirs; /* our children */
};
注意:
- 每个文件其实都要有对应的dentry结构,包括普通文件。这样所有被打开的文件,就可以在内存中形成整个树形结构。
- 整个树形节点也同时会⾪属于LRU(Least Recently Used,最近最少使用)结构中,进行节点淘汰。
- 整个树形节点也同时会⾪属于Hash,方便快速查找。
- 更重要的是,这个树形结构,整体构成了Linux的路径缓存结构,打开访问任何文件,都在先在这棵树下根据路径进行查找,找到就返回属性inode和内容,没找到就从磁盘加载路径,添加dentry结构,缓存新路径。
7.挂载分区
我们已经能够根据inode号在指定分区找⽂件了,也已经能根据⽬录⽂件内容,找指定的inode了,在
指定的分区内,我们可以为所欲为了。可是:
问题:inode不是不能跨分区吗?Linux不是可以有多个分区吗?我怎么知道我在哪⼀个分区???
root@hcss-ecs-b3aa:~# ls /dev/vda* //查看磁盘: 其中vda是磁盘, vda1是分区
/dev/vda /dev/vda1
root@hcss-ecs-b3aa:~# dd if=/dev/zero of=./disk.iso bs=1M count=5 //制作一个大的磁盘块,就当做一个分区
root@hcss-ecs-b3aa:~# mkfs.ext4 disk.iso //格式化写入文件系统
root@hcss-ecs-b3aa:/# mkdir /mnt/myvda2 //建立空目录
root@hcss-ecs-b3aa:/# df -h //查看可以使用的分区
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 5.0G 33G 14% /
root@hcss-ecs-b3aa:/# mount -t ext4 ./disk.iso /mnt/myvda2 //将分区挂载到指定的目录
root@hcss-ecs-b3aa:/# df -h //再次查看可以使用的分区
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 5.0G 33G 14% /
/dev/loop0 4.7M 24K 4.4M 1% /mnt/myvda2
root@hcss-ecs-b3aa:/# cd /mnt/myvda2 //进入该分区
root@hcss-ecs-b3aa:/mnt/myvda2# cd / //回到该分区
//所以: 在哪个路径下, 就能通过df -h查看在哪一个分区中
root@hcss-ecs-b3aa:/# umount /mnt/myvda2 //卸载分区
root@hcss-ecs-b3aa:/mnt/myvda2# ls /dev/loop* -l
brw-rw---- 1 root disk 7, 0 Feb 13 16:31 /dev/loop0
brw-rw---- 1 root disk 7, 1 Feb 13 16:31 /dev/loop1
brw-rw---- 1 root disk 7, 2 Feb 13 16:32 /dev/loop2
brw-rw---- 1 root disk 7, 3 Feb 13 16:32 /dev/loop3
brw-rw---- 1 root disk 7, 4 Feb 13 16:31 /dev/loop4
brw-rw---- 1 root disk 7, 5 Feb 15 15:22 /dev/loop5
brw-rw---- 1 root disk 7, 6 Feb 13 16:31 /dev/loop6
brw-rw---- 1 root disk 7, 7 Feb 13 16:31 /dev/loop7
crw-rw---- 1 root disk 10, 237 Feb 13 16:31 /dev/loop-control
结论:分区写入文件系统,无法直接使用,需要和指定的目录关联,进行挂载(Mounted on)才能使用。所以,可以根据访问目标文件的 “路径前缀” 准确判断我在哪一个分区。
8.文件系统总结
四.软硬链接
1.软链接
xzy@hcss-ecs-b3aa:~/code$ ln -s file.txt file.softlink #建立file.txt的软链接文件file.softlink
xzy@hcss-ecs-b3aa:~/code$ ls -li
total 0
530971 lrwxrwxrwx 1 xzy xzy 8 Feb 15 16:06 file.softlink -> file.txt
530970 -rw-rw-r-- 1 xzy xzy 0 Feb 15 16:05 file.txt
软链接:本质是一个独立的文件,拥有独立的inode,block。其中inode保存该文件的属性,block保存的是目标文件的路径。在Windows下类似快捷方式,根据目标文件的路径打开目标文件。
xzy@hcss-ecs-b3aa:~/code$ mkdir -p dir1/dir2/dir3
xzy@hcss-ecs-b3aa:~/code$ mv test.exe ./dir1/dir2/dir3
xzy@hcss-ecs-b3aa:~/code$ tree .
.
├── dir1
│ └── dir2
│ └── dir3
│ └── test.exe
└── test.c
xzy@hcss-ecs-b3aa:~/code$ ln -s ./dir1/dir2/dir3/test.exe test #给文件建立软链接
xzy@hcss-ecs-b3aa:~/code$ ls -l
total 8
drwxrwxr-x 3 xzy xzy 4096 Feb 15 18:59 dir1
lrwxrwxrwx 1 xzy xzy 25 Feb 15 19:01 test -> ./dir1/dir2/dir3/test.exe
-rw-rw-r-- 1 xzy xzy 72 Feb 15 18:55 test.c
xzy@hcss-ecs-b3aa:~/code$ ./test
Hello Linux!
xzy@hcss-ecs-b3aa:~/code$ ln -s /usr/include inc #给目录建立软链接
xzy@hcss-ecs-b3aa:~/code$ ls -l
total 0
lrwxrwxrwx 1 xzy xzy 12 Feb 15 19:04 inc -> /usr/include
xzy@hcss-ecs-b3aa:~/code$ cd inc #本质进入/usr/include目录中
xzy@hcss-ecs-b3aa:~/code/inc$ pwd
/home/xzy/code/inc
2.硬链接
xzy@hcss-ecs-b3aa:~/code$ ln file.txt file.hardlink #建立file.txt的硬链接文件file.hardlink
xzy@hcss-ecs-b3aa:~/code$ ls -li
total 0
530970 -rw-rw-r-- 2 xzy xzy 0 Feb 15 16:05 file.hardlink
530970 -rw-rw-r-- 2 xzy xzy 0 Feb 15 16:05 file.txt
硬链接:本质不是一个独立的文件,没有独立的inode。硬链接文件的inode与目标文件的inode相同,在当前目录中新增硬链接文件名与inode的映射关系。所以在Linux中可以让多个文件名对应于同一个inode。上面的2是inode中的引用计数 -> 硬链接数
xzy@hcss-ecs-b3aa:~/code$ tree .
.
└── empty
└── dir
xzy@hcss-ecs-b3aa:~/code$ ls -lia
total 12
529723 drwxrwxr-x 3 xzy xzy 4096 Feb 15 19:30 .
524310 drwxr-x--- 6 xzy xzy 4096 Feb 15 18:55 ..
530946 drwxrwxr-x 3 xzy xzy 4096 Feb 15 19:14 empty
xzy@hcss-ecs-b3aa:~/code$ cd empty/
xzy@hcss-ecs-b3aa:~/code/empty$ ls -lia
total 12
530946 drwxrwxr-x 3 xzy xzy 4096 Feb 15 19:14 .
529723 drwxrwxr-x 3 xzy xzy 4096 Feb 15 19:30 ..
530972 drwxrwxr-x 2 xzy xzy 4096 Feb 15 19:14 dir
xzy@hcss-ecs-b3aa:/$ ls -lid /
2 drwxr-xr-x 20 root root 4096 Feb 15 15:15 /
#根目录的硬链接数是20, 减去.和根目录自己, 计算出根目录下存在18个目录
结论:.是当前路径的硬链接 ..是上一级路径的硬链接
xzy@hcss-ecs-b3aa:~/code$ echo "This is 10TB data" > log.txt
xzy@hcss-ecs-b3aa:~/code$ ln log.txt /tmp/log.txt.backup #在/tmp目录下建立硬链接
xzy@hcss-ecs-b3aa:~/code$ rm -rf log.txt
xzy@hcss-ecs-b3aa:~/code$ cat /tmp/log.txt.backup
This is 10TB data
结论:硬链接可以用来文件备份
注意:
- 不能给目录进行硬链接(容易造成环型路径,硬链接的上级目录有两个,存在歧义),至于
.和..
是内置的,不考虑。 - 可以给目录进行软链接(存在环型路径,但是软链接的文件类型为 l,遇到系统知道)