inode和逻辑块,目录的结构,挂载的实现 源码级分析linux内核的文件系统的结构

news2024/12/29 10:43:33

在这里插入图片描述

bitmap.c 位图相关

封装了set_bit clear_bit find_first_zero clear_block等操作位图的宏

对应i节点位图和逻辑块位图有对应的四个函数 free_inode, new_inode,free_block, new_block

new_block 创建逻辑块

通过super_block找到逻辑块位图,给逻辑块位图的第一个空闲位(find_first_zero) 置1 (set_bit),获得逻辑块号后,通过getblk(dev,j)来申请一个缓冲块指向设备中的逻辑块,清空缓冲块,从而让对应的设备上的逻辑块清空。bh->b_dirt = 1出现了两次,一次是修改逻辑块位图要落盘,一次是new逻辑块要落盘。

free_block 释放逻辑块

通过super_block找到逻辑块位图,给逻辑块位图的对应的占用位置0 (clear_bit),同时使得hash_table中的该块对应的缓冲块(如果有的话)失效bh->b_uptodate=0

  • 有了缓冲区的存在创建和释放逻辑块的速度非常快,不涉及到同步IO,后面会在某个时刻将buffer同步到设备上的逻辑块。创建和释放也只是操作位图

new_inode 创建i节点

通过super_block找到i节点位图,给i节点位图的第一个空闲位(find_first_zero) 置1 (set_bit),获得i节点号后,通过get_empty_inode取得inode_table中空闲i节点,设置i_count,i_dev,i_num,即说明dev设备的num号i节点被使用(count)。i_dirt,b_dirt都置1,修改的i节点位图要落盘,新的i节点要落盘

free_inode 释放i节点

通过super_block找到i节点位图,给i节点位图的对应的占用位置0 (clear_bit),同时使得inode_table中的该i节点失效memset(inode,0,sizeof(*inode))

inode.c i节点相关

read_inode 读i节点 static

从设备上读取含有指定i节点信息的i节点(d_inode)盘块,然后复制到指定的i节点(m_inode)结构中。

write_inode 写i节点 static

把参数指定的i节点(m_inode)写入缓冲区相应的缓冲块(d_inode)中,bh->b_dirt=1,待缓冲区刷新时会写入盘中。i节点内容已经与缓冲区中的一致,因此修改标志置零inode->i_dirt=0

iget 取一个i节点

首先在位于高速缓冲区中的i节点表中搜寻,若找到指定节点号的i节点则在经过一些判断处理后返回该i节点指针。否则read_inode从设备dev上读取指定i节点号的i节点信息放入i节点表中,并返回该i节点指针。

iput 放回一个i节点

该函数主要用于把i节点引用计数值递减1,并且若是管道i节点,则唤醒等待的进程。若是块设备文件i节点则刷新设备。并且若i节点的链接计数为0,则释放该i节点占用的所有磁盘逻辑块,并释放该i节点。

get_empty_inode

从i节点表(inode table)中获取一个空闲i节点项,寻找引用计数count为0的i节点,并将其写盘后清零,返回其指针。引用计数被置1。

bmap/create_block (f, x) = y

文件数据块映射到盘块的处理操作。(block位图处理函数,bmap: block map) 对于文件f中的第x个数据块,对应的是磁盘上的逻辑块y,返回y,后续根据(dev, y)去访问文件。create_block即为文件f(也可能是目录)的第x个数据块分配一个逻辑块y
在这里插入图片描述

namei.c 目录/软硬链接

add_entry/find_entry static

在这里插入图片描述

添加/查找dir目录下的name目录项,通过res_dir返回目录项,以及目录项所在缓冲区的buffer_head,因为之后肯定涉及到目录项的修改,buffer_head->dirt =1

static struct buffer_head * add_entry(struct m_inode * dir,
	const char * name, int namelen, struct dir_entry ** res_dir)
static struct buffer_head * find_entry(struct m_inode ** dir,
	const char * name, int namelen, struct dir_entry ** res_dir)

get_dir static

// 搜寻指定路径名的目录(或文件名)的i节点。
// 参数:pathname-路径名。
// 返回:目录或文件的i节点指针。失败时返回NULL。
// usr/src/linux  : src						  linux不是最顶层目录,因为后面没有/
// usr/src/linux/ : linux
// usr/src/linux/1.txt : linux                可知道最顶层目录是  [xxx]/的形式
static struct m_inode * get_dir(const char * pathname)

dir_namei static

/*
 *	dir_namei函数返回指定目录名的i节点指针,以及在最顶层目录的名称。
 */
// 参数:pathname-目录路径名:namelen-路径名长度:name-返回的最顶层目录名。
// 返回:指定目录名最顶层目录的i节点指针 | 最顶层目录名称及长度。      
// pathname: /home/zyx/video  则 namelen:5 name:video          
// 出错时返回NULL。注意!! 这里"最顶层目录"是指路径名中最靠近末端的目录。
// usr/src/linux  : 		返回src			name:linux		len:5					  
// usr/src/linux/ :			返回linux		name:""			len:0
// usr/src/linux/1.txt : 	返回linux       name:1.txt   	len:4
static struct m_inode * dir_namei(const char * pathname,
	int * namelen, const char ** name)

namei

// 取指定路径名的i节点 
// pathname:路径名
// 返回对应的i节点
// 即:
// usr/src/ 				src节点				dir_namei后返回src
// usr/src/linux			src下搜linux目录	iget后返回linux
// usr/src/linux/1.txt: 	linux下搜1.txt文件	iget后返回1.txt
struct m_inode * namei(const char * pathname)

*open_namei

根据路径名返回对应的i节点。

// namei
// 参数filename是文件名,flag是打开文件标志,它可取值:O_RDONLY(只读)、O_WRONLY
// (只写)或O_RDWR(读写),以及O_CREAT(创建)、O_EXCL(被创建文件必须不存在)、
// O_APPEND(在文件尾添加数据)等其他一些标志的组合。如果本调用创建了一个新文件,则
// mode就用于指定文件的许可属性。这些属性有S_IRWXU(文件宿主具有读、写和执行权限)、
// S_IRUSR(用户具有读文件权限)、S_IRWXG(组成员具有读、写和执行权限)等等。对于新
// 创建的文件,这些属性只应用于将来对文件的访问,创建了只读文件的打开调用也将返回一
// 个可读写的文件句柄。参见相关文件sys/stat.h、fcntl.h。
// 返回:成功返回0,否则返回出错码:res_inode 返回对应文件路径名的i节点指针。
int open_namei(const char * pathname, int flag, int mode,
	struct m_inode ** res_inode)

目录相关的系统调用 mkdir rmdir link unlink

super.c 挂载是怎么实现的

get_super

取指定设备的超级块,在超级块表(数组)中搜索指定设备dev的超级块结构信息。若找到则返回超级块的指针,否则返回空指针。

read_super

读取超级块信息,如果内存中的超级块数组没有该块,bh = bread(dev,1)直接读超级块到超级块数组中

*((struct d_super_block *) s) = *((struct d_super_block *) bh->b_data);检查i节点位图和逻辑块位图中的block数量 和 2+s->s_imap_blocks+s->s_zmap_blocks记录块数进行对比。

mount 挂载

mount相关的函数有三个,分别是 sys_umount sys_mount mount_root。把一个 mount -o ro /dev/hda1 /mnt 挂载会影响super_block的s_imount字段,以及挂在对应i节点的i_mount字段,后续在iget取节点时,如果是个挂在节点,就会返回对应的挂载的设备和i节点号

if (inode->i_mount)
    dev = super_block[i].s_dev;
	nr = ROOT_INO;

在这里插入图片描述

truncate.c

free_ind static

释放一次间接块

free_dind static

释放二次间接块

truncate

将节点对应的文件长度截为0,并释放占用的设备空间

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

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

相关文章

Spring Boot中的bean注入方式和原理

Spring Boot是一个非常流行的Java框架,它可以帮助开发者快速地构建高效、健壮的应用程序。依赖注入是Spring Boo其中一个重要的功能,就是将一个对象注入到另一个对象中,以便它们可以相互协作。在Spring Boot中,依赖注入是通过bean…

Python如何获取大量电影影评,做可视化演示

前言 《保你平安》今天上映诶,有朋友看过吗,咋样啊 这是我最近比较想看的电影了,不过不知道这影评怎么样,上周末的点映应该是有蛮多人看的吧,可以采集采集评论看过的朋友发出来的评论,分析分析 这周刚好…

2023年斋月倒计时,跨境卖家该如何做好选品和营销?

2023年斋月即将到来,这是一个伊斯兰教徒们非常重要的节日,同时也是跨境卖家们迎接销售高峰的时期。在2023年的斋月期间,跨境卖家应该如何做好选品和营销呢?本文Nox聚星将和大家好好聊一聊。 根据2022年的数据,斋月期间…

【巨人的肩膀】MySQL面试总结(一)

💪 目录💪1、什么是ER图2、数据库范式了解吗3、超键、候选键、主键、外键分别是什么?4、为什么不推荐使用外键与级联5、什么是存储过程6、drop、delete与truncate区别7、数据库设计通常分为那几步8、什么是关系型数据库9、什么是SQL10、MySQL…

SpringBoot整合Redis实现高并发数据缓存

目录什么是缓存为什么要用缓存Redis为什么这么快实现一个用户信息的缓存方式一:利用RedisTemplate实现导入依赖添加配置添加redis工具类及配置类开发mapper接口service层controller层测试方式二:采用SpringBoot注解开启缓存在启动类添加EnableCaching注解…

旋转框目标检测mmrotate v1.0.0rc1 之RTMDet训练DOTA的官方问题解析整理(四)

关于rotated_rtmdet_l-coco_pretrain-3x-dota_ms.py配置文件的batchsize和学习率设置问题:回答:如何在mmrotate中绘制特征图问题:回答:你好AllieLan,您可以尝试使用https://github.com/open-mmlab/mmyolo/blob/main/de…

Java Class 加密工具 ClassFinal

Jar包加密工具 ClassFinal介绍环境依赖使用说明下载加密命令行示例maven插件方式无密码模式机器绑定启动加密后的jar启动参数给密码不加密码参数直接启动1. 密码文件获取2. 交互输入参考资料介绍 ClassFinal 是一款 java class 文件安全加密工具,支持直接加密jar包…

KDHL-600A 回路电阻测试仪

一、产品概述 武汉凯迪正大KDHL-600A回路电阻测试仪是用于测量开关、断路器、变压器等设备的接触电阻、回路电阻的专用测试设备。其采用典型的四线制测量法,通过输出一个直流电流,施加于被测体的两个端钮之间,并测量电流流过被测体所产生的压…

Node.js简介

客户端访问网页时向服务器端发送请求要访问服务器中的页面,服务器收到请求后向数据库中进行搜索,搜索到相关数据然后返回结果给客户端显示; 这个过程就类似于:客人(客户端)去饭馆(服务端&#…

TryHackMe-VulnNet: Active(ez 域渗透)

VulnNet: Active VulnNet Entertainment在他们以前的网络中遇到了不好的时光,该网络遭受了多次破坏。现在,他们移动了整个基础架构,并再次聘请您作为核心渗透测试人员。您的目标是获得对系统的完全访问权限并破坏域。 这应该是我在thm打的最…

Uipath Excel 自动化系列15-Protect Sheet(保护工作表)

活动描述 Protect Sheet(保护工作表):在 Excel 中启用对指定工作表的保护,以便无法对其进行任何其他更改,该活动需与Use Excel File 活动选择的 Excel 文件一起使用。 提示:Protect Sheet活动功能类似Excel文件【审阅】菜单栏下的保护工作簿功能&#…

TencentOS Server 安装 PostgreSQL

TencentOS 简介 2019 年,随着腾讯公司外部客户的需求,以及公司开源协同战略的推进,tlinux 对外开源并进行了品牌升级,升级为 TencentOS Server。TencentOS 包含三大场景,分别如下: TencentOS Server&…

MySQL DQL语句基础(一)

目录 DQL 基本语法 基础查询 1、查询多个字段 2、字段设置别名 3、去除重复记录 条件查询 语法 条件 案例 聚合函数 常见的聚合函数 语法 DQL DQL英文全称是Data Query Language(数据查询语言),数据查询语言,用来查询数据库中表的记录。 基…

java面试-jvm

JVM JVM 是 java 虚拟机,简单来说就是能执行标准 java 字节码的虚拟计算机 JVM 是如何工作的 首先程序在执行之前先要把 Java 代码(.java)转换成字节码(.class),JVM 通过类加载器(ClassLoade…

Linux:创建守护进程,注册信号捕获回调函数,使用shell脚本代码管理守护进程

1.创建守护进程&#xff0c;编译时命名为a.out. 2.在守护进程中注册信号捕捉函数。 3.使用脚本发送自定义信号SIGUSR1给进程a.out。 4.守护进程捕获函数catchSignal&#xff08;&#xff09;捕捉到10号函数SIGUSR1退出进程。 创建守护进程代码&#xff1a; #include <stdi…

第八批国家药品集中采购-(附药品集采目录明细下载)

2023年3月2日&#xff0c;‘国家组织药品联合采购办公室’发出了《全国药品集中采购文件》&#xff0c;宣告了第八批国家组织药品集中采购工作正式开展&#xff0c;其公告中还包含三个附表分别为‘采购品种目录’、‘各地区首年约定采购量’、‘各采购品种首年约定采购量’&…

python for循环中 if else语句缩进对应问题

python for循环中 if else语句缩进对应问题 忙里偷闲&#xff0c;备考计算机二级&#xff0c;发现一个好玩的小知识&#xff0c;想分享一下自己当时的思考以及解决问题的过程 也许点进来的你会莫名其妙&#xff0c;if和else语句的缩进必须对齐&#xff0c;这不是连初学者都一…

【数据结构】带你深入理解栈

一. 栈的基本概念&#x1f4ab;栈是一种特殊的线性表。其只允许在固定的一端进行插入和删除元素的操作&#xff0c;进行数据的插入和删除的一端称作栈顶&#xff0c;另外一端称作栈底。栈不支持随机访问&#xff0c;栈的数据元素遵循后进先出的原则&#xff0c;即LIFO&#xff…

怎么把pdf转换成图片?这个方法你值得拥有

想要高效率的工作&#xff0c;除了需要大家合理安排时间之外&#xff0c;一些能够辅助高效工作的工具也是必不可少的。就拿要把一份pdf文件转换成若干图片来说&#xff0c;如果不知道方法&#xff0c;找不到合适的转换工具&#xff0c;那么想要完成这一任务&#xff0c;势必要花…

万里长征——基础IO

目录 文件常识 回顾C语言的文件操作 系统层面的文件操作 文件操作的本质 文件fd的分配规则及重定向 linux下一切皆文件 详谈缓冲区问题 文件常识 1、文件 文件内容 文件属性 2、空文件也要在磁盘上占据空间。因为空文件虽然内容为空&#xff0c;但它的属性也会占据空…