Linux系统--文件系统

大家好,我们今天继续来学习Linux系统部分。上一次我们学习了内存级的文件,下面我们来学习磁盘级的文件。那么话不多说,我们开始今天的学习:


目录

Ext系列⽂件系统

1. 理解硬件

1-1 磁盘、服务器、机柜、机房

1-2 磁盘物理结构

1-3 磁盘的存储结构

1-4 磁盘的逻辑结构

1-4-1 理解过程

1-4-2 真实过程

1-5 CHS && LBA地址

2. 引⼊⽂件系统

2-1 引⼊"块"概念

2-2 引⼊"分区"概念

2-3 引⼊"inode"概念

3. ext2 ⽂件系统

3-1 宏观认识

3-2 Block Group

3-3 块组内部构成

3-3-1 超级块(Super Block)

3-3-2 GDT(Group Descriptor Table)

3-3-3 块位图(Block Bitmap)

3-3-4 inode位图(Inode Bitmap)

3-3-5 i节点表(Inode Table)

3-3-6 Data Block

3-4 inode和datablock映射

3-5 ⽬录与⽂件名

3-6 路径解析

3-7 路径缓存

3-8 挂载分区

3-9 ⽂件系统总结

4. 软硬连接

4-1 硬链接

4-2 软链接

4-3 软硬连接对⽐

4-4 软硬连接的⽤途


Ext系列⽂件系统

1. 理解硬件

我们想要访问文件,需要通过基础I/O来把磁盘中的文件加载到内存中。所以被打开的文件存储在内存中,没有被打开的文件存储在磁盘中。那么我们该如何从磁盘上找到我们想要的文件呢?不着急,我们先来认识一下磁盘:

1-1 磁盘、服务器、机柜、机房

机械磁盘是计算机中唯⼀的⼀个机械设备
磁盘--- 外设
特点:
容量⼤,价格便宜

这两张图是磁盘的结构,

将一组磁盘整合到一起,就是一个服务器,

将服务器再整合到一起,就是一个机柜,

机柜再整合到一起就是一个机房,这一整套系统都是用来进行存储的。磁盘有许多种,每种磁盘的存储方式也有不同,机械磁盘通过磁存储,其工作原理完全围绕磁铁和磁场展开;固态硬盘通过电荷的保存与读取来记录数据,下面我们以机械磁盘举例来学习:

1-2 磁盘物理结构

磁盘通过盘片的转动和磁头的摆动来将数据存储到磁盘的不同位置

1-3 磁盘的存储结构

扇区:是磁盘存储数据的基本单位,512字节,块设备

磁盘并不是一个单层的结构,一个磁盘通常由多个盘片和磁头组成,每个盘片的正反面都可以进行存储,每个面对应一个磁头,比如说三张盘片就要对应六个磁头。但需要注意的是,这些磁头都由一个机械臂控制,因此所有磁头的运动轨迹是相同的。

我们将盘片分为多个同心圆,每一个同心圆都是一个磁道,每一个磁道又被分为多个扇区,扇区就是磁盘进行存储的最小单位。所有面的相同磁道被称为柱面。

所以在定位一个扇区时,磁头先摆动到该柱面位置,再确定该扇区对应哪一个磁头,随后盘片转动再定位该扇区,这样的定位方式叫做CHS地址定位

1. 扇区是从磁盘读出和写⼊信息的最⼩单位,通常⼤⼩为 512 字节。
2. 磁头(head)数:每个盘⽚⼀般有上下两⾯,分别对应1个磁头,共2个磁头
3. 磁道(track)数:磁道是从盘⽚外圈往内圈编号0磁道,1磁道...,靠近主轴的同⼼圆⽤于停靠磁头,不存储数据
4. 柱⾯(cylinder)数:磁道构成柱⾯,数量上等同于磁道个数
5. 扇区(sector)数:每个磁道都被切分成很多扇形区域,每道的扇区数量相同
6. 圆盘(platter)数:就是盘⽚的数量
7. 磁盘容量=磁头数 × 磁道(柱⾯)数 × 每道扇区数 × 每扇区字节数
CHS寻址对早期的磁盘⾮常有效,知道⽤哪个磁头,读取哪个柱⾯上的第⼏扇区就可以读到数据了。
但是CHS模式⽀持的硬盘容量有限,因为系统⽤8bit来存储磁头地址,⽤10bit来存储柱⾯地
址,⽤6bit来存储扇区地址,⽽⼀个扇区共有512Byte,这样使⽤CHS寻址⼀块硬盘最⼤容量
为256 * 1024 * 63 * 512B = 8064 MB(1MB = 1048576B)(若按1MB=1000000B来算就是
8.4GB)
1-4 磁盘的逻辑结构

为此,要找到一种更为方便的寻址方式,难道磁盘只有光盘这样一种形式的吗?

1-4-1 理解过程

这是磁带,通常来存储音乐,把磁带拆开来看,把磁带拉直,它的结构是长条的。也就是说,我们可以认为磁带的存储是线性结构

那么磁盘本质上虽然是硬质的,但是逻辑上我们可以把磁盘想象成为卷在⼀起的磁带,那么磁盘的逻辑存储结构我们也可以类似于:

这样我们可以为每⼀个扇区提供⼀个线性地址(其实就是数组下标),这种地址叫做LBA

1-4-2 真实过程
由于传动臂上的磁头是共进退的,所以磁头在运动时对于每个盘片来说能访问的位置都是相同的

那么我们把每⼀⾯上,相同半径的磁道逻辑上构成柱⾯,所以,磁盘物理上分了很多⾯,但是在我们看来,逻辑上,磁盘整体是由“柱⾯”卷起来的。
所以,磁盘的真实情况是:
磁道:
某⼀盘⾯的某⼀个磁道展开:

即:⼀维数组
柱⾯:
整个磁盘所有盘⾯的同⼀个磁道,即柱⾯展开:

柱⾯上的每个磁道,扇区个数是⼀样的,那就是⼆维数组
整盘:

整个磁盘不就是多张⼆维的扇区数组表(三维数组?)
所以,寻址⼀个扇区:先找到哪⼀个柱⾯(Cylinder) ,在确定柱⾯内哪⼀个磁道(其实就是磁头位置,Head),在确定扇区(Sector),所以就有了CHS。

我们将其全转换成一维数组:

现在我们为每一个扇区都提供一个下标,我们叫做LBA(Logical Block Address)地址,其实就是线性地址。所以怎么计算得到这个LBA地址呢?

1-5 CHS && LBA地址
CHS转成LBA:
1. 磁头数*每磁道扇区数 = 单个柱⾯的扇区总数
2. LBA = 柱⾯号C*单个柱⾯的扇区总数 + 磁头号H*每磁道扇区数 + 扇区号S - 1
3. 即:LBA = 柱⾯号C*(磁头数*每磁道扇区数) + 磁头号H*每磁道扇区数 + 扇区号S - 1
4. 扇区号通常是从1开始的,⽽在LBA中,地址是从0开始的
5. 柱⾯和磁道都是从0开始编号的
6. 总柱⾯,磁道个数,扇区总数等信息,在磁盘内部会⾃动维护,上层开机的时候,会获取到这些参数。
LBA转成CHS:
1. 柱⾯号C = LBA // (磁头数*每磁道扇区数)【就是单个柱⾯的扇区总数】
2. 磁头号H = (LBA % (磁头数*每磁道扇区数)) // 每磁道扇区数
3. 扇区号S = (LBA % 每磁道扇区数) + 1
4. "//": 表⽰除取整
从此往后,在磁盘使⽤者看来,根本就不关⼼CHS地址,⽽是直接使⽤LBA地址,磁盘内部⾃⼰转换。所以:
从现在开始,磁盘就是⼀个 元素为扇区 的⼀维数组,数组的下标就是每⼀个扇区的LBA地址。OS使⽤磁盘,就可以⽤⼀个数字访问磁盘扇区了。
2. 引⼊⽂件系统
2-1 引⼊"块"概念
其实硬盘是典型的“块”设备,操作系统读取硬盘数据的时候,其实是不会⼀个个扇区地读取,这样效率太低,⽽是⼀次性连续读取多个扇区,即⼀次性读取⼀个”块”(block)。
硬盘的每个分区是被划分为⼀个个的”块”。⼀个”块”的⼤⼩是由格式化的时候确定的,并且不可以更改,最常⻅的是4KB,即连续⼋个扇区组成⼀个 ”块”。”块”是⽂件存取的最⼩单位。
注意:
磁盘就是⼀个三维数组,我们把它看待成为⼀个"⼀维数组",数组下标就是LBA,每个元素都是扇区
每个扇区都有LBA,那么8个扇区⼀个块,每⼀个块的地址我们也能算出来。
知道LBA:块号 = LBA/8
知道块号:LAB=块号*8 + n. (n是块内第⼏个扇区)

2-2 引⼊"分区"概念
其实磁盘是可以被分成多个分区(partition)的,以Windows观点来看,你可能会有⼀块磁盘并且将它分区成C,D,E盘。那个C,D,E就是分区。分区从实质上说就是对硬盘的⼀种格式化。但是Linux的设备都是以⽂件形式存在,那是怎么分区的呢?

柱⾯是分区的最⼩单位,我们可以利⽤参考柱⾯号码的⽅式来进⾏分区,其本质就是设置每个区的起始柱⾯和结束柱⾯号码。 此时我们可以将硬盘上的柱⾯(分区)进⾏平铺,将其想象成⼀个⼤的平⾯,如下图所⽰:

2-3 引⼊"inode"概念
之前我们说过 ⽂件=数据+属性 ,我们使⽤ ls -l 的时候看到的除了看到⽂件名,还能看到⽂件元数据(属性)。
[root@localhost linux]# ls -l
总⽤量 12
-rwxr-xr-x. 1 root root 7438 "9⽉ 13 14:56" a.out
-rw-r--r--. 1 root root 654 "9⽉ 13 14:56" test.c
每⾏包含7列:
模式
硬链接数
⽂件所有者
⼤⼩
最后修改时间
⽂件名
ls -l读取存储在磁盘上的⽂件信息,然后显⽰出来

其实这个信息除了通过这种⽅式来读取,还有⼀个stat命令能够看到更多信息
[root@localhost linux]# stat test.c
File: "test.c"
Size: 654 Blocks: 8 IO Block: 4096 普通⽂件
Device: 802h/2050d Inode: 263715 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2017-09-13 14:56:57.059012947 +0800
Modify: 2017-09-13 14:56:40.067012944 +0800
Change: 2017-09-13 14:56:40.069012948 +0800
到这我们要思考⼀个问题,⽂件数据都储存在”块”中,那么很显然,我们还必须找到⼀个地⽅储存⽂件的元信息(属性信息),⽐如⽂件的创建者、⽂件的创建⽇期、⽂件的⼤⼩等等。这种储存⽂件元信息的区域就叫做inode,中⽂译名为”索引节点”。

文件的内容和属性是分开存储的,每⼀个⽂件都有对应的inode,⾥⾯包含了与该⽂件有关的⼀些信息。为了能解释清楚inode,我们需要是深⼊了解⼀下⽂件系统。

所以⼀个⽂件的属性inode⻓什么样⼦呢?

/*
* Structure of an inode on the disk
*/
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 */union {struct {__le32 l_i_reserved1;} linux1;struct {__le32 h_i_translator;} hurd1;struct {__le32 m_i_reserved1;} masix1;} osd1; /* OS dependent 1 */__le32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */__le32 i_generation; /* File version (for NFS) */__le32 i_file_acl; /* File ACL */__le32 i_dir_acl; /* Directory ACL */__le32 i_faddr; /* Fragment address */union {struct {__u8 l_i_frag; /* Fragment number */__u8 l_i_fsize; /* Fragment size */__u16 i_pad1;__le16 l_i_uid_high; /* these 2 fields */__le16 l_i_gid_high; /* were reserved2[0] */__u32 l_i_reserved2;} linux2;struct {__u8 h_i_frag; /* Fragment number */__u8 h_i_fsize; /* Fragment size */__le16 h_i_mode_high;__le16 h_i_uid_high;__le16 h_i_gid_high;__le32 h_i_author;} hurd2;struct {__u8 m_i_frag; /* Fragment number */__u8 m_i_fsize; /* Fragment size */__u16 m_pad1;__u32 m_i_reserved2[2];} masix2;} osd2; /* OS dependent 2 */
};
/*
* Constants relative to the data blocks
*/
#define EXT2_NDIR_BLOCKS 12
#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
⽂件名属性并未纳⼊到inode数据结构内部
inode的⼤⼩⼀般是128字节或者256,我们后⾯统⼀128字节
任何⽂件的内容⼤⼩可以不同,由于属性存储在结构体变量中,所以属性⼤⼩⼀定是相同的

简单介绍了分区结构,下面我们来具体认识一下文件系统

3. ext2 ⽂件系统
3-1 宏观认识

我们想要在硬盘上储⽂件,必须先把硬盘格式化为某种格式的⽂件系统,才能存储⽂件。⽂件系统的⽬的就是组织和管理硬盘中的⽂件。在Linux 系统中,最常⻅的是 ext2 系列的⽂件系统。其早期版本为 ext2,后来⼜发展出 ext3 和 ext4。
ext3 和 ext4 虽然对 ext2 进⾏了增强,但是其核⼼设计并没有发⽣变化,我们仍是以较⽼的 ext2 作为演⽰对象。
ext2⽂件系统将整个分区划分成若⼲个同样⼤⼩的块组 (Block Group),如下图所⽰。只要能管理⼀个分区就能管理所有分区,也就能管理所有磁盘⽂件。

上图中启动块(Boot Block/Sector)的⼤⼩是确定的,为1KB,由PC标准规定,⽤来存储磁盘分区信息和启动信息,任何⽂件系统都不能修改启动块。启动块之后才是ext2⽂件系统的开始。

由图可见,文件系统是以分区为载体的,一块磁盘被分为不同的区,每个区都是一个文件系统,每个文件系统又被分为多个组,在每个组内部的空间,又有着不同的功能,下面我们来介绍一下:

3-2 Block Group
ext2⽂件系统会根据分区的⼤⼩划分为数个Block Group。⽽每个Block Group都有着相同的结构组成。
3-3 块组内部构成
3-3-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; /* Inodes count */__le32 s_blocks_count; /* Blocks count */__le32 s_r_blocks_count; /* Reserved blocks count */__le32 s_free_blocks_count; /* Free blocks count */__le32 s_free_inodes_count; /* Free inodes count */__le32 s_first_data_block; /* First Data Block */__le32 s_log_block_size; /* Block size */__le32 s_log_frag_size; /* Fragment size */__le32 s_blocks_per_group; /* # Blocks per group */__le32 s_frags_per_group; /* # Fragments per group */__le32 s_inodes_per_group; /* # Inodes per group */__le32 s_mtime; /* Mount time */__le32 s_wtime; /* Write time */__le16 s_mnt_count; /* Mount count */__le16 s_max_mnt_count; /* Maximal mount count */__le16 s_magic; /* Magic signature */__le16 s_state; /* File system state */__le16 s_errors; /* Behaviour when detecting errors */__le16 s_minor_rev_level; /* minor revision level */__le32 s_lastcheck; /* time of last check */__le32 s_checkinterval; /* max. time between checks */__le32 s_creator_os; /* OS */__le32 s_rev_level; /* Revision level */__le16 s_def_resuid; /* Default uid for reserved blocks */__le16 s_def_resgid;__le32 s_first_ino; /* First non-reserved inode */__le16 s_inode_size; /* size of inode structure */__le16 s_block_group_nr; /* block group # of this superblock */__le32 s_feature_compat; /* compatible feature set */__le32 s_feature_incompat; /* incompatible feature set */__le32 s_feature_ro_compat; /* readonly-compatible feature set */__u8 s_uuid[16]; /* 128-bit uuid for volume */char s_volume_name[16]; /* volume name */char s_last_mounted[64]; /* directory where last mounted */__le32 s_algorithm_usage_bitmap; /* For compression */__u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/__u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */__u16 s_padding1;__u8 s_journal_uuid[16]; /* uuid of journal superblock */__u32 s_journal_inum; /* inode number of journal file */__u32 s_journal_dev; /* device number of journal file */__u32 s_last_orphan; /* start of list of inodes to delete */__u32 s_hash_seed[4]; /* HTREE hash seed */__u8 s_def_hash_version; /* Default hash version to use */__u8 s_reserved_char_pad;__u16 s_reserved_word_pad;__le32 s_default_mount_opts;__le32 s_first_meta_bg; /* First metablock block group */__u32 s_reserved[190]; /* Padding to the end of the block */
};
3-3-2 GDT(Group Descriptor Table)

块组描述符表,描述块组属性信息,整个分区分成多个块组就对应有多少个块组描述符。每个块组描述符存储⼀个块组 的描述信息,如在这个块组中从哪⾥开始是inode Table,从哪⾥开始是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-3-3 块位图(Block Bitmap)
Block Bitmap中记录着Data Block中哪个数据块已经被占⽤,哪个数据块没有被占⽤
3-3-4 inode位图(Inode Bitmap)
每个bit表⽰⼀个inode是否空闲可⽤。
3-3-5 i节点表(Inode Table)
存放⽂件属性 如 ⽂件⼤⼩,所有者,最近修改时间等
当前分组所有Inode属性的集合
inode编号以分区为单位,整体划分,不可跨分区
3-3-6 Data Block
数据区:存放⽂件内容,也就是⼀个⼀个的Block。根据不同的⽂件类型有以下⼏种情况:
对于普通⽂件,⽂件的数据存储在数据块中。
对于⽬录,该⽬录下的所有⽂件名和⽬录名存储在所在⽬录的数据块中,除了⽂件名外,ls -l命令看到的其它信息保存在该⽂件的inode中。
Block 号按照分区划分,不可跨分区
3-4 inode和datablock映射

inode内部存在 __le32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ , EXT2_N_BLOCKS =15,就是⽤来进⾏inode和block映射的

索引块是用来记录文件实际占用的字节数,一个一级索引块可以存储1024个直接块的指针,让用户和系统能够了解文件的规模

inode 和数据块,跨组编号的,inode 和数据块,不能跨分区。所以,在同一个分区内部,inode 编号,和块号都是唯一的,在不同的分区内,可以使用相同的inode编号。

我们使用文件的inode编号就能找到这个文件的所有内容和属性数据

3-5 ⽬录与⽂件名

那么话又说回来了,为什么文件名不被存储在inode中呢?

因为在Linux中,目录也被视作是文件,所以目录的存储也是按照如上方式进行的,对于目录来说,内容保存的是:⽂件名和Inode号的映射关系,所以若目录中有重名文件时,这种映射就会产生冲突,导致无法准确找到文件对应的 inode,进而无法获取文件的信息和实际数据。

访问⽂件,必须打开当前⽬录,根据⽂件名,获得对应的inode号,然后进⾏⽂件访问
访问⽂件必须要知道当前⼯作⽬录,本质是必须能打开当前⼯作⽬录⽂件,查看⽬录⽂件的内容!
所以我们访问⽂件时,可以⽤的⽂件名,不用inode号。
3-6 路径解析

我们访问文件的时候,谁来给我们提供路径呢?

我们需要通过进程来访问文件,所以由进程来提供路径

问题:打开当前⼯作⽬录⽂件,查看当前⼯作⽬录⽂件的内容?当前⼯作⽬录不也是⽂件吗?我们访问当前⼯作⽬录不也是只知道当前⼯作⽬录的⽂件名吗?要访问它,不也得知道当前⼯作⽬录的inode吗?
答案1:所以也要打开:当前⼯作⽬录的上级⽬录,额....,上级⽬录不也是⽬录吗??不还是上⾯的问题吗?
答案2:所以类似"递归",需要把路径中所有的⽬录全部解析,出⼝是"/"根⽬录。
最终答案3:⽽实际上,任何⽂件,都有路径,访问⽬标⽂件,⽐如:
/home/user/code/test/test/test.c
都要从根⽬录开始,依次打开每⼀个⽬录,根据⽬录名,依次访问每个⽬录下指定的⽬录,直到访问到test.c。这个过程叫做Linux路径解析。
所以,我们知道了:访问⽂件必须要有⽬录+⽂件名=路径的原因
根⽬录固定⽂件名,inode号,⽆需查找,系统开机之后就必须知道
3-7 路径缓存
问题1:Linux磁盘中,存在真正的⽬录吗?
答案:不存在,只有⽂件。只保存⽂件属性+⽂件内容
问题2:访问任何⽂件,都要从/⽬录开始进⾏路径解析?
答案:原则上是,但是这样太慢,所以Linux会缓存历史路径结构
问题2: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* negative *//** The next three fields are touched by __d_lookup. Place them here* so they all fit in a cache line.*/struct hlist_node d_hash; /* lookup hash list */struct dentry *d_parent; /* parent directory */struct qstr d_name;struct list_head d_lru; /* LRU list *//** d_child and d_rcu can share memory*/union {struct list_head d_child; /* child of parent list */struct rcu_head d_rcu;} d_u;struct list_head d_subdirs; /* our children */struct list_head d_alias; /* inode alias list */unsigned long d_time; /* used by d_revalidate */struct dentry_operations *d_op;struct super_block *d_sb; /* The root of the dentry tree */void *d_fsdata; /* fs-specific data */
#ifdef CONFIG_PROFILINGstruct dcookie_struct *d_cookie; /* cookie, if any */
#endifint d_mounted;unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */
};
1. 每个⽂件其实都要有对应的dentry结构,包括普通⽂件。这样所有被打开的⽂件,就可以在内存中形成整个树形结构
2. 整个树形节点也同时会⾪属于LRU(Least Recently Used,最近最少使⽤)结构中,进⾏节点淘汰
3. 整个树形节点也同时会⾪属于Hash,⽅便快速查找
4. 更重要的是,这个树形结构,整体构成了Linux的路径缓存结构,打开访问任何⽂件,都在先在这棵树下根据路径进⾏查找,找到就返回属性inode和内容,没找到就从磁盘加载路径,添加dentry结构,缓存新路径

3-8 挂载分区

我们已经能够根据inode号在指定分区找⽂件了,也已经能根据⽬录⽂件内容,找指定的inode了,在指定的分区内,我们可以为所欲为了。可是:
问题:inode不是不能跨分区吗?Linux不是可以有多个分区吗?我怎么知道我在哪⼀个分区???
分区写⼊⽂件系统,⽆法直接使⽤,需要和指定的⽬录关联,进⾏挂载才能使⽤。
所以,可以根据访问⽬标⽂件的"路径前缀"准确判断我在哪⼀个分区。
3-9 ⽂件系统总结

4. 软硬连接
4-1 硬链接

我们看到,真正找到磁盘上⽂件的并不是⽂件名,⽽是inode。其实在linux中可以让多个⽂件名对应于同⼀个inode。
[root@localhost linux]# touch abc
[root@localhost linux]# ln abc def
[root@localhost linux]# ls -li abc def
263466 abc
263466 def
abc和def的链接状态完全相同,他们被称为指向⽂件的硬链接。内核记录了这个连接数,inode263466 的硬连接数为2。
我们在删除⽂件时⼲了两件事情:1.在⽬录中将对应的记录删除,2.将硬连接数-1,如果为0,则将对应的磁盘释放。

硬链接不是一个独立的文件,因为它没有独立的inode,硬链接本质上是多一个文件名指向对应的目标文件,很像c++中的引用,所以硬链接可以用来做文件备份。

4-2 软链接
硬链接是通过inode引⽤另外⼀个⽂件,软链接是通过名字引⽤另外⼀个⽂件,但实际上,新的⽂件和被引⽤的⽂件的inode不同,应⽤常⻅上可以想象成⼀个快捷⽅式。
[root@localhost linux]# ln -s abc.s abc
[root@localhost linux]# ls -li
263563 -rw-r--r--. 2 root root 0 9⽉ 15 17:45 abc
261678 lrwxrwxrwx. 1 root root 3 9⽉ 15 17:53 abc.s -> abc
263563 -rw-r--r--. 2 root root 0 9⽉ 15 17:45 def

用一张图来表示软硬连接就是:

4-3 软硬连接对⽐
软连接是独⽴⽂件
硬连接不是独立文件只是⽂件名和⽬标⽂件inode的映射关系
4-4 软硬连接的⽤途
硬链接
1. 目录中的... 就是硬链接
2. ⽂件备份
软连接
1. 类似快捷⽅式

好了今天关于文件系统的内容就是这些,如果有收获的话还请点个赞支持一下,我们下次再见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/92343.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/92343.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

KUKA库卡焊接机器人氩气节气设备

在焊接生产过程中,氩气作为一种重要的保护气体被广泛应用于KUKA库卡焊接机器人的焊接操作中。氩气的消耗往往是企业生产成本的一个重要组成部分,因此实现库卡焊接机器人节气具有重要的经济和环保意义。WGFACS节气装置的出现为解决这一问题提供了有效的方…

远程连接----ubuntu ,rocky 等Linux系统,WindTerm_2.7.0

新一代开源免费的终端工具-WindTerm github 27.5k⭐ https://github.com/kingToolbox/WindTerm/releases/download/2.7.0/WindTerm_2.7.0_Windows_Portable_x86_64.zip 主机填写你自己要连接的主机ip 端口默认 22 改成你ssh文件配置的端口 输入远程的 用户名 与密码 成功连接…

笔试——Day32

文章目录第一题题目思路代码第二题题目:思路代码第三题题目:思路代码第一题 题目 素数回文 思路 模拟 构建新的数字,判断该数是否为素数 代码 第二题 题目: 活动安排 思路 区间问题的贪⼼:排序,然…

超高车辆如何影响城市立交隧道安全?预警系统如何应对?

超高车辆对立交隧道安全的潜在威胁在城市立交和隧道中,限高设施的设计通常考虑到大部分正常通行的货车和运输车辆。然而,一些超高的货车、集装箱车或特殊车辆如果未经有效监测而进入限高区域,就可能对道路设施造成极大的安全隐患。尤其在立交…

解决 MinIO 上传文件时报 S3 API Requests must be made to API port错误

在使用 MinIO 进行文件上传时&#xff0c;我遇到了一个比较坑的问题。错误日志如下&#xff1a; io.minio.errors.InvalidResponseException: Non-XML response from server. Response code: 400, Content-Type: text/xml; charsetutf-8, body: <?xml version"1.0&quo…

linux_https,udp,tcp协议(更新中)

目录 https 加密类型 对称加密 非对称加密 加密方案 只用对程加密 只用非对程加密 双方都是用非对程加密 非对称对称加密 非对称对称加密证书 流程图 校验流程图 udp udp协议格式 特点 UDP缓冲区 tcp tcp协议格式 32位序号及确认序号 4位首部 6位标志位 1…

web端-登录页面验证码的实现(springboot+vue前后端分离)超详细

目录 一、项目技术栈 二、实现效果图 ​三、实现路线 四、验证码的实现步骤 五、完整代码 1.前端 2.后端 一、项目技术栈 登录页面暂时涉及到的技术栈如下: 前端 Vue2 Element UI Axios&#xff0c;后端 Spring Boot 2 MyBatis MySQL JWT Maven 二、实现效果图…

疯狂星期四文案网第33天运营日记

网站运营第33天&#xff0c;点击观站&#xff1a; 疯狂星期四 crazy-thursday.com 全网最全的疯狂星期四文案网站 运营报告 今日访问量 今日搜索引擎收录情况 必应收录239个页面&#xff0c;还在持续增加中&#xff0c;已经获得必应的认可&#xff0c;逐渐收录所有页面 百度…

客户端利用MinIO对服务器数据进行同步

MinIO 是一款高性能、开源的对象存储服务&#xff0c;专为海量数据存储设计&#xff0c;兼容 Amazon S3 API&#xff08;即与 AWS S3 协议兼容&#xff09;&#xff0c;可用于构建私有云存储、企业级数据湖、备份归档系统等场景。它以轻量、灵活、高效为核心特点&#xff0c;广…

WPF 双击行为实现详解:DoubleClickBehavior 源码分析与实战指南

WPF 双击行为实现详解:DoubleClickBehavior 源码分析与实战指南 文章目录 WPF 双击行为实现详解:DoubleClickBehavior 源码分析与实战指南 引言 一、行为(Behavior)基础概念 1.1 什么是行为? 1.2 行为的优势 二、DoubleClickBehavior 源码分析 2.1 类定义与依赖属性 2.2 双…

零知开源——基于STM32F103RBT6的TDS水质监测仪数据校准和ST7789显示实战教程

✔零知开源是一个真正属于国人自己的开源软硬件平台&#xff0c;在开发效率上超越了Arduino平台并且更加容易上手&#xff0c;大大降低了开发难度。零知开源在软件方面提供了完整的学习教程和丰富示例代码&#xff0c;让不懂程序的工程师也能非常轻而易举的搭建电路来创作产品&…

luogu P3387 【模板】缩点

原题链接 原题再现 题目描述 给定一个 n 个点 m 条边有向图&#xff0c;每个点有一个权值&#xff0c;求一条路径&#xff0c;使路径经过的点权值之和最大。你只需要求出这个权值和。 允许多次经过一条边或者一个点&#xff0c;但是&#xff0c;重复经过的点&#xff0c;权…

P1119 灾后重建【题解】

P1119 灾后重建 题目背景 B 地区在地震过后&#xff0c;所有村庄都造成了一定的损毁&#xff0c;而这场地震却没对公路造成什么影响。但是在村庄重建好之前&#xff0c;所有与未重建完成的村庄的公路均无法通车。换句话说&#xff0c;只有连接着两个重建完成的村庄的公路才能通…

Horse3D引擎研发笔记(二):基于QtOpenGL使用仿Three.js的BufferAttribute结构重构三角形绘制

在Horse3D引擎的研发过程中&#xff0c;我们致力于构建一个高效、灵活且易于扩展的3D图形引擎。在本篇博客中&#xff0c;我们将详细记录如何基于QtOpenGL框架&#xff0c;使用仿Three.js的BufferAttribute结构&#xff0c;重构三角形绘制流程。通过这一过程&#xff0c;我们希…

MCU程序段的分类

程序的下载&#xff08;烧录到存储器中&#xff09;通常是按照程序文件分段&#xff08;Code段、RO_data段、RW_data段、ZI_data段&#xff09;的方式存储的&#xff0c;但运行时内存的布局会按照程序进程分段&#xff08;TEXT段、DATA段、BSS段、堆栈段&#xff09;进行组织。…

综合项目记录:自动化备份全网服务器数据平台

一、项目背景与需求1.1项目概述该项目共分为2个子项目&#xff0c;由环境搭建和实施备份两部分组成1.2项目总体需求企业内部有一台web服务器&#xff0c;内部数据很重要&#xff0c;现需要为该web服务器数据做备份&#xff0c;这样在数据丢失时可以恢复。要求如下&#xff1a;每…

联合索引全解析:一棵树,撑起查询的半边天

目录 一、为什么联合索引是MySQL性能优化的“王牌”&#xff1f; &#xff08;一&#xff09;索引的基本结构&#xff1a;从聚簇到非聚簇 1. 聚簇索引&#xff08;Clustered Index&#xff09; 2. 非聚簇索引&#xff08;Secondary Index&#xff09; &#xff08;二&…

vue开发的计算机课程页面

课程信息展示页面设计与实现我将设计一个美观且实用的课程信息展示页面&#xff0c;重点展示计算机网络应用课程的相关信息。设计思路使用卡片式布局清晰展示课程各模块信息采用科技感配色方案&#xff0c;符合计算机网络课程主题添加动画效果增强用户体验响应式设计确保在各种…

MySQL 正则表达式详细说明

目录 MySQL 正则表达式详细说明 1. 基本操作符&#xff1a;REGEXP 和 RLIKE 2. 常用正则表达式模式 3. MySQL 正则表达式函数&#xff08;MySQL 8.0&#xff09; 4. 示例查询 5. 注意事项 6. 总结 MySQL 正则表达式详细说明 MySQL 支持正则表达式&#xff08;Regular Ex…

c++之 栈浅析

C之栈浅析 概要 通过可视化游戏梳理栈特点以及栈操作方式. 学习栈的工作原理就像往糖果罐里放糖果和拿糖果一样简单&#xff01; 栈特点 先进后出 技术名词解释 LIFO LIFO -> Last In, First Out 后进先出 可视化小游戏 游戏传送门