ext2文件系统(2)inode,datablock映射,路径解析与缓存,分区挂载,软硬连接

本章目标

1.inode与datablock映射

2.目录与文件名

3.路径解析

4.路径缓存

5.分区挂载

6.软硬连接

1.inode与datablock映射

我们之前说过inode保存着一个文件的大部分属性信息,我们管它叫做元数据

其种inode中有一个inode number的东西来标识一个文件用来区分其他文件的标识

它其种也包含着datablock它所占用的的块号我们可以通过内核看一眼

就是这个结构可是我们看到这个结构才15个大小啊

它是怎么进行存储大量的块号的呢

其他在磁盘当中一个inode是通过分级存储的方式来存储块号

在这个数组当中前12个数据块用来直接进行存储数据块

一个数据块的大小是4kb,也就是48kb

当大于这个值他就会用二级存储

这个指针指向的是一张索引表

这个数据块用来存储其他数据块的块号

我们假设一个地址用4个字节

它就会增加4096/4=1024个数据块的大小

10241024 4=4mb的大小

当超过这个大小之后,他就会用二级索引

它第一个指针指向的就是第一个索引表

对于二级索引来说,它的这个索引表指向的是下一个索引表

第二个索引表指向的才是真正数据块的块号

也就是10241024 10244 =4g
对于3级索引来说就是4g
1024 =4tb的大小

这也就是解决了存储大文件的内容

那么我们既然知道了文件的inode号和inode和datablock是如何进行映射的
那么一个文件是如何进行创建删除修改查找的呢

1创建:

对于创建来说,我们首先会在内存当中为这个文件创建inode,并写入属性信息,然后再由os在inode bitmap中找到一个没有使用的地方,分配inode号,然内存中的inode通过inode将自身刷入inode table当中.如果由数据的话,会在block bitmap当中找到空闲的块号,然后根据块号填写上面的映射表,把数据写入到对应的数据块当中

2.删除

对于删除,我们会在inode bitmap找到对应inode号去查inode table,找到对应的映射表,把block bitmap中的内容全部置为0,最后再将inode bitmap对应的位置置0即可.

3.修改

对于修改,一定遵守的是下面的规则,先加载,再修改 ,再刷新.

我们需要把对应的文件加载到内存当中,在内存当中修改,最后刷新到磁盘当中.

刷新的过程如创建一样.

4.查找.

我们只需要拿到对应的inode号,就能找到inode,根据inode就能够找到对应的文件信息

2.目录与文件名

可是在前面,我们并没有使用过inode去查找一个文件,而是使用文件名去查找的

这里我们就需要理解文件目录了.

在Linux当中一切皆文件,

对于目录来说,它也是文件.对于一个文件它一定有自己的数据,数据就分为属性和内容.

对于目录的属性在前面,我们通过权限已经见过了.

今天我们要谈的是文件目录的内容

对于文件目录的内容来说,它存储的就是文件名和inode的映射.

所以我们就可以通过文件名去访问inode了

c 复制代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>  
#include <dirent.h>  
#include <sys/types.h>  
#include <unistd.h>  
int main(int argc, char *argv[]) {  
if (argc != 2) {  
fprintf(stderr, "Usage: %s <directory>\n", argv[0]);  
exit(EXIT_FAILURE);  
}  
DIR *dir = opendir(argv[1]);  // 
系统调⽤,⾃⾏查阅
 
if (!dir) {  
perror("opendir");  
exit(EXIT_FAILURE);  
}  
struct dirent *entry;  
while ((entry = readdir(dir)) != NULL) {   // 
系统调⽤,⾃⾏查阅
 
// Skip the "." and ".." directory entries  
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") 
== 0) {  
continue;  
}  
printf("Filename: %s, Inode: %lu\n", entry->d_name, (unsigned 
long)entry->d_ino); 
}  
closedir(dir);  
return 0;  
}

大家可以用上面的代码验证一下.

在这里我们要重新讨论下块号和inode编号了

对于一块磁盘,我们是不可能使用到100%的利用率的.

实际上一个inode有多少,一个inode一般分配多少块号都是固定好的.

但是这都是经验值.如果在系统里大文件多,在inode和块号的分配比就小一点,1:50

如果大文件多那么就100个块号分配一个inode

所以是存在inode还是可是创建不处文件出来的情况

所以inode和块号都是不可跨分区的.

3.路径解析

那么我们向找到一个文件,就必须去查看该文件的工作目录,可是这个目录也是文件啊,那他去找上级目录.

而这个类似如递归的过程,我们就叫做解析.而出口是根目录

如果我们访问一个目标文件.哪一般都是有目录的/home/whb/code/test/test/test.c

都要从根⽬录开始,依次打开每⼀个⽬录,根据⽬录名,依次访问每个⽬录下指定的⽬录,直到访问到test.c。这个过程叫做Linux路径解析。

对于根目录,根⽬录固定⽂件名,inode号,⽆需查找,系统开机之后就必须知道

对于路径是谁提供的?

1.进程通过自身的cwd来提供,我们一般都是通过指令和工具来使用,本质上都是进程访问

2.open文件的时候由用户指定的

4.路径缓存

我们了解了路径解析,但是我们的Linux如何每次打开一个文件都去解析,效率就太低了.

所以我们的Linux将我们曾经的路径缓存起来,就方便我们下一次查找了.

在内核当中,维护的结构是struct dentery

问题1:Linux磁盘中,存在真正的⽬录吗?

答案:不存在,只有⽂件。只保存⽂件属性+⽂件内容

问题2:访问任何⽂件,都要从/⽬录开始进⾏路径解析?

答案:原则上是,但是这样太慢,所以Linux会缓存历史路径结构

问题2:Linux⽬录的概念,怎么产⽣的?

答案:打开的⽂件是⽬录的话,由OS⾃⼰在内存中进⾏路径维护

每个⽂件其实都要有对应的dentry结构,包括普通⽂件。这样所有被打开的⽂件,就可以在内存中形成整个树形结构,普通文件就是这颗目录树的叶子节点

整个树形节点也同时会⾪属于LRU(LeastRecentlyUsed,最近最少使⽤)结构中,进⾏节点淘汰

整个树形节点也同时会⾪属于Hash,⽅便快速查找

更重要的是,这个树形结构,整体构成了Linux的路径缓存结构,打开访问任何⽂件,都在先在这棵树下根据路径进⾏查找,找到就返回属性inode和内容,没找到就从磁盘加载路径,添加dentry结构,缓存新路径

5.分区挂载

在前面我们说过inode和块号,那么我们是如何进行区分分区之间的inode的呢?,我们怎么知道我们的inode是哪个分区的?

我们做个实验

powershell 复制代码
dd if=/dev/zero if=./disk.img bs=1M count=5

我们伪造一个大文件作为磁盘

powershell 复制代码
mkfs.ext4 disk.img

这一步是向这个文件写入管理信息,就是格式化,创建文件系统

用ext系列的文件系统即可

当我们向这个磁盘当中写入管理信息,这个文件系统也用不了

我们需要把它挂在在一个分区上,

我们可以通过 df -h来查看一个磁盘的使用情况

powershell 复制代码
sudo mount -t ext4 ./disk.img /mnt/mydisk

通过mount指令将分区进行挂载

这样我们就可以使用这个磁盘了

我们的linux是根据最长路径进行匹配的,我们可以在这个路径下创建文件

通过umount来卸载分区

没有东西了

分区写⼊⽂件系统,⽆法直接使⽤,需要和指定的⽬录关联,进⾏挂载才能使⽤。

所以,可以根据访问⽬标⽂件的"路径前缀"准确判断我在哪⼀个分区。

6.软硬连接

硬链接

我们看到,真正找到磁盘上⽂件的并不是⽂件名,⽽是inode。其实在linux中可以让多个⽂件名对应于同⼀个inode。

我们可以通过ln命令创建硬链接

通过ls -i选项查看inode

硬链接主要有两个方面的应用.

1.给文件创建备份,主要是大文件.

对于一个文件的删除如果文件的映射关系大于等于2,都是删的映射关系.

只有变为1才会去真正去删除文件

2... 和...就是硬链接.除了这两个文件目录其他的目录不能够创建硬链接

因为会有回路的问题.

软连接

硬链接是通过inode引⽤另外⼀个⽂件,软链接是通过名字引⽤另外⼀个⽂件,但实际上,新的⽂件和被引⽤的⽂件的inode不同,应⽤常⻅上可以想象成⼀个快捷⽅式。在shell中的做法

我们通过ln -s方法创建软连接

软连接是真正意义上的文件.它是有自己独立的inode的

相关推荐
鱼香rose__2 小时前
Linux远程登录-SSH
linux·运维·ssh
源代码•宸2 小时前
Leetcode—146. LRU 缓存【中等】(哈希表+双向链表)
后端·算法·leetcode·缓存·面试·golang·lru
搞全栈小苏2 小时前
嵌入式之 LVGL 的切换页面研究:杜绝内存泄漏(单片机与 Linux 平台)(链表与多进程方式)
linux·单片机·链表·lvgl
☀Mark_LY2 小时前
elasticsearch7集群Linux部署
linux·elasticsearch
2501_944521592 小时前
Flutter for OpenHarmony 微动漫App实战:骨架屏加载实现
android·开发语言·javascript·数据库·redis·flutter·缓存
承渊政道2 小时前
C++学习之旅【C++Vector类介绍—入门指南与核心概念解析】
c语言·开发语言·c++·学习·visual studio
hetao17338372 小时前
2026-01-21~22 hetao1733837 的刷题笔记
c++·笔记·算法
时艰.2 小时前
Redis 核心知识点归纳与详解
数据库·redis·缓存
鱼香rose__2 小时前
git的基本使用
linux·git