inode结点

article/2025/10/2 23:26:24

一、 机械硬盘

1.1 工作原理

写入时,磁头线圈加电,在周围产生磁场,磁化其下的磁性材料;电流的方向不同,所以磁场的方向也不同,可以表示 0 和 1 的区别。——“电生磁”。

读取时,磁头线圈(不加电)切割磁场线产生感应电流,磁性材料的磁场方向不同,所以产生的感应电流方向也不同。可以表示出 0 和 1 的区别。——“磁生电”。

硬盘保存数据是有时间限制的,当硬盘消磁后,存储在硬盘里的数据就读不出来了。

1.2 扇区

硬盘的基本存储单位扇区sector),每个扇区一般为512byte。一个硬盘往往会有多个盘片,每个盘片分成两面,每面按照同心圆划分为若干个磁道,每个磁道分为若干个扇区

图1 柱面、磁头
图2-1 磁道、扇区(合理)
图2-2 磁道、扇区(不合理)

如图1 所示:具有相同磁道编号的同心圆组成柱面。那么需要知道某个扇区的具体位置,需要知道柱面号磁头号扇区号。每个盘面同心圆的周长不一样。如图2-2 所示,如果按照每个磁道都拥有相同数量的扇区,那么外围的磁道密度肯定比内圈更加稀疏。但是如果不同的磁道扇区数量不同,计算起来就十分麻烦。产商们最终选择了图2-1 所示的方案。为了屏蔽这些复杂的硬件细节,现代的硬盘普遍使用一种叫做 LBAlogical block address)的方式,即整个硬盘中的所有扇区从0开始编号,一直到最后一个扇区。这个扇区编号叫做逻辑扇区号。在最外圈从0开始编号,缘由将在1.3 节给出。

逻辑扇区号抛弃了所有复杂的磁道、盘面之类的概念。当我们给出一个逻辑的扇区号时,硬盘的电子设备会将其转换成实际的盘面、磁道等这些位置。


 在Linux操作系统中,要读取这个文件的前4096个字节时,会使用一个read系统调用来实现。文件系统收到 read 请求之后,判断出文件的前 4096 个字节位于磁盘的 1000 号逻辑扇区到 1007号逻辑扇区。然后文件系统就向磁盘驱动发出一个读取逻辑扇区为 1000 号开始的 8 个扇区的请求,磁盘驱动程序收到这个请求以后就向硬盘发出硬件命令。向硬盘发送 I/O 命令的方式有很多种,最为常见的一种就是通过读写 I/O 寄存器来实现。在 x86 平台上,共有65 536 (12位)个硬件端口寄存器,不同的硬件被分配到不同的 I/O 端口地址。CPU 提供了两条专门的指令 “in” 和 “out” 来实现对硬件端口的读写。

对 IDE 接口来说,它有两个通道,分别为 IDE0 和 IDE1 ,每个通道上可以连接两个设备,分别为 Master 和 Slave ,一个 PC 中最多可以有 4 个 IDE 设备。假设我们的文件位于 IDE0 的 Master 硬盘上,这也是正常情况下硬盘所在的位置。在 PC 中,IDE0 通道的 I/O 端口地址是 0x1F0~0x1F7 及 0x376~0x377。通过读写这些端口地址就能和 IDE 硬盘进行通信。这些端口的作用和操作方式十分复杂,我们就以实现读取 1000 号逻辑扇区开始的 8 个扇区为例:

  • 第0x1F3~0x1F6 4个字节的端口地址是用来写入 LBA 地址的,那么 1000 号的逻辑扇区的 LBA 地址为 0x0000 03E8,所以我们需要往0x1F3、0x1F4 写入 0x00,往 0x1F5 写入0x03,往 0x1F6 写入0xE8。

  • 0x1F2 这个地址是用来写入命令所需要读写的扇区数。比如读取 8 个扇区即写入 8。

  • 0x1F7 这个地址是用来写入要执行的操作的命令码,对于读取操作来说,命令字为 0x20。所以我们要执行的命令为:

out 0x1F3, 0x00
out 0x1F4, 0x00
out 0x1F5, 0x03
out 0x1F6, 0xE8
out 0x1F2, 0x08
out 0x1F7, 0x20

硬盘收到这个命令以后,它就会执行相应的操作,并且将数据读取到事先设置好的内存地址中(这个地址也是通过类似的命令方式设置的)。

1.3 操作系统

硬盘的磁道定义是从外圈往内圈排顺序,最外圈为零磁道,用于存放引导信息。操作系统也是从最外圈开始安装的。外圈磁道相对内圈磁道更长读写数据更稳定

1.4 块 

文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector)。每个扇区储存512字节(相当于0.5KB)。操作系统读取硬盘的时候,不会一个一个扇区进行读取——效率太低,而是一次性连续读取多个扇区,即一次性读取一个"块"(block)。问题就来了!需要在效率和磁盘利用率之间做一个折中。

由多个扇区组成的"块",是文件存取的最小单位。

文件数据都储存在"块"中,还必须找到一个地方储存文件的元信息(metadata, 就是文件的"属性, 描述信息"),如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode(identifier),中文译名为"索引节点"。

图3 磁盘有无可用空间的因素

磁盘格式化创建文件系统时会生成一定数量的inode和block。磁盘空间是否满了,是由两项参数决定的:inode满或是block满,任何一个满了都不能存放数据。

二、 深入理解inode

2.1 概述

disk(磁盘)          memeory(内存)

Linux把inode分为两种方式保存,一种是在硬盘中的inode(d_inode),一种是在内存中的inode(m_inode)。m_inode除了完全包含d_inode中的字段之外还有一些专门的字段。

图4 目录项结构

如图4 所示:每个文件的目录项存储在该文件所属目录中。inode是文件的唯一标识,文件名和inode的对应关系存放在上一级目录的block中;inode所含字段包含指向文件block的指针和文件的属性等,通过block获得文件数据。 


图5 文件存储结构

如图5 所展示的那样,通过inode访问步骤如下:

  1. 在目录文件中找到文件名对应的inode编号;如图3 所示;
  2. 利用inode号,获取inode信息;
  3. 根据inode信息,找到文件数据所在的block,读出数据。

 


图6 访问流程

2.2 inode所含字段 

图7 inode结构示意图

如图 7所示:

  • 字节数。
  • UID、GID。
  • 读、写、执行权限(w-r-x)。
  • ctime:inode最后修改时间;mtime:文件内容最后变动时间;atime:文件最后打开时间。
  • 链接数:有多少文件名指向这个inode。
  • 块(block)的位置(指向文件block的指针)。

2.3 inode大小

inode会消耗硬盘空间。硬盘格式化的时候,操作系统自动将硬盘分成两个区域。一个是数据区(存放文件数据);另一个是inode区(inode table)(存放inode)。

每个inode节点的大小,一般是128byte或256byte。inode节点的总数,在格式化时就给定,一般是每1KB或每2KB就设置一个inode。假定在一块1GB的硬盘中,每个inode节点的大小为128字节,每1KB就设置一个inode,那么inode table的大小就会达到128MB,占整块硬盘的12.8%。

2.4 d_inode

struct d_inode
{unsigned short i_mode;//I结点的模式——如读、写、执行权限。
//i_mode一共10位,第一位表明结点文件类型,后9位依次为:I结点所有者、所属组成员、其他成员的权限(权限有读写执行三种)。unsigned short i_uid;    //I结点的user id。unsigned long i_size;    //I结点文件的大小。unsigned long i_time;    //I结点创建时间。unsigned char i_gid;    //I结点的组id。unsigned char i_nlinks;    //表明有多少进程链接到此结点。unsigned short i_zone[9];    //文件数据对应在磁盘上的位置。
}

这里要说明一点:由于在Linux0.01内核中,数据最终是存放在磁盘上的。而磁盘存放数据的单位是块(block),大小为1KB。对于小于 7K 的文件,文件信息可直接反映在inode中。(I结点字段 i_zone 的前7个元素来存放前7块数据在磁盘上的地址)。对于大文件,inode 通过利用间接块的方式来支持。i_zone[7] 存放的是一级间接块的地址(一级间接块指向512个数据块),i_zone[8]存放的是二级间接块的地址(二级间接块指向512个一级间接块)。

图8 理解进程PCB

正如图8 所展示的那般:Linux最大可以支持(7+512+512×512)KB ≈ 256.51MB 大小的文件。

2.5 m_inode

m_inode 是存放在内存中的I结点,会比 d_inode 多一些字段,具体字段如下:

struct m_inode
{unsigned short i_mode;    unsigned short i_uid;unsigned long i_size;unsigned long i_mtime;unsigned char i_gid;unsigned char i_nlinks;unsigned short i_zone[9];//以下是m_inode特有的字段struct task_struct* i_wait;    //task_struct是进程pCB结构。I结点的等待队列。unsigned long i_atime;    //文件上次访问时间。unsigned long i_ctime;    //I结点修改时间,注意和i_mtime区别。unsigned short i_dev;    //表明此结点所属的设备号。unsigned short i_num;    //I结点的结点号。unsigned short i_count;    //I结点被打开次数,主要用于判断文件是否共享!unsigned char i_lock;    //判断I结点是否被锁住。unsigned char i_dirt;    //判断I结点是否需要写回磁盘。unsigned char i_pipe;    //判断I结点是否为管道文件。unsigned char i_mount;    //如果有文件系统安装在此结点上,则置此位。//以下字段Linux0.01版本没有用到。unsigned char i_seek;    //在lseek调用时置此位。unsigned char i_update; 
};

2.6 软链接、硬链接

正如图1 所展示的,通过文件名(带路径,不带路径极可能重复)在该文件的目录文件中找到其对应的目录项,文件名和inode号是唯一对应关系。凭着inode号在inode table找出对应的inode结点。

图9 软硬链接示意图

正如图9 所展示的,硬链接hardlink.c 和原文件helloa.c 指向都inode1,不管硬链接hardlink.c还是原文件helloa.c,都可以根据inode1访问block块;软链接softlink.c 指向inode2,通过inode2访问链接文件(该文件主要内容是原文件文件名),通过链接文件获得文件名,通过文件名获得inode1;根据inode1的信息,访问block块。链接文件和原文件是依存的关系。

文件是在磁盘上存放的,删除文件并不是真正删除磁盘上的文件,而是将block块对应的inode链接数减一,同时在目录文件中删除目录项。inode引用计数减到0时也不会真正去删除文件,而是等待新文件内容将其覆盖。


软、硬链接不同点:

  1. 硬链接原文件和新文件的inode编号一致。而软链接不一样。
  2. 对原文件删除,会导致软链接不可用,而硬链接不受影响。这就是第一条性质导致的。

软、硬链接相同点:

  1. 对原文件的修改,软、硬链接文件内容也一样的修改,因为都是指向同一个文件内容的。

http://chatgpt.dhexx.cn/article/lpNivQZy.shtml

相关文章

什么是inode?

理解inode,要从文件储存说起。文件储存在硬盘上,硬盘的最小存储单位叫扇区(Sector)。每个扇区储存512字节(相当于0.5KB)。操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区&…

inode详解

文章目录 什么是inode?inode的内容(inode是一个结构体)block区和inode区的理解inode编号硬链接软连接 什么是inode? 理解inode,要从文件储存说起。 文件储存在硬盘上,硬盘的最小存储单位叫做"扇区&quo…

代码编写流程

文章目录 代码编写步骤好的代码满足条件:注意事项 代码编写步骤 1、分析任务目标,根据目标选择合适的代码设计模式   1.1、创建模式选择   1.2、结构模式选择   1.3、行为模式选择 2、整理思路、画出思维导图、或代码流程图 3、找到其中的关键对象…

代码详解设计模式--模板模式

模板模式 一个抽象类公开定义了执行方法的模板,它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。 优点: 封装不变部分,扩展可变部分。提取公共代码,便于维护。行为由父类控制,子类实现…

GRID-FORM 基于 VUE3 可视化低代码表单设计器

本文开源代码在 GRID-FORM,如能帮到您麻烦给个星哈 楔子 大概 4 年前,我做了一个简单的动态表单功能,开发人员通过 UI 界面配置表单(其实就是添加常用的控件,如文本框、下拉框等)就能向用户提供数据查询&a…

领域驱动实践总结(基本理论总结与分析+架构分析与代码设计+具体应用设计分析V)

目录 领域驱动实践总结三:具体应用设计分析 一、应用项目的基本背景 二、针对项目进行领域驱动的战略设计阶段 (一)事件风暴确定产品愿景 (二)事件风暴进行业务场景分析 场景分析一:请假 用户:…

领域驱动实践总结(基本理论总结与分析+架构分析与代码设计V+具体应用设计分析)

目录 领域驱动实践总结二:架构分析与代码设计 一、微服务架构模型的对比与选择 (一)整洁架构 (二)六边形架构 (三)DDD 分层架构 1.用户接口层 2.应用层 3.领域层 4.基础层 5.从三层架构向 DDD 分…

十二种常见设计模式代码详解

零:设计模式分类 设计模式有创建型模式、结构型模式与行为型模式 创建型:单例模式、工厂模式(简单工厂,工厂方法,抽象工厂)结构型:适配器模式、门面模式、装饰器模式、注册树模式、代理模式、…

优雅代码的秘密,都藏在这6个设计原则中

优雅的代码,犹如亭亭玉立的美女,让人赏心悦目。而糟糕的代码,却犹如屎山,让人避而远之。 如何写出优雅的代码呢?那就要理解并熟悉应用这6个设计原则啦:开闭原则、单一职责原则、接口隔离原则 、迪米特法则…

低代码--低代码开发(LCDP)介绍

低代码开发(LCDP)介绍 1 介绍1.1 概述1.2 行业风向1.3 行业报告1.4 优点减少重复编程避免沟通隔阂提升效率 1.5 挑战完全抛弃代码的代价,就是平台能力与灵活性受限应用低代码平台阻力大技术局限老旧系统改造困难职业角色缺失应用者大多是技术…

网页设计个人主页代码

/ 01 / 前话 主题《周末の守候》采用Dreamweaver软件制作,主题包含了12页,页面能够相互跳转,运用了HTML5标签,DIVCSS布局,网站主题鲜明、内容丰富、健康、高雅且栏目设置合理,网站中页面色彩搭配合理&…

#低码系列#如何设计一个低代码平台?

低码系列文章 #低码系列#低代码来了,程序员会失业吗? 整体设计 用户群体 对于基础功能的实现,不需要开发人员介入。业务人员通过可视化页面,即可完成设计。从这个角度上看,低码平台面向的用户是业务人员、系统管理…

浅谈代码结构的设计

本文来自网易云社区 作者:陆秋炜 引言 :很久之前,在做中间件测试的时候,看到开发人员写的代码,有人的代码,看起来总是特别舒服,但有的开发代码,虽然逻辑上没有什么问题,但总给人感觉特别难受。后来成为了一位专职开发人员,渐渐发现,自己的代码也是属于“比较难受”…

领域驱动实践总结(基本理论总结与分析V+架构分析与代码设计+具体应用设计分析)

目录 领域驱动实践总结一:基本理论总结与分析 一、领域驱动设计两大设计:战略设计和战术设计 (一)战略设计 1.出发角度与目标 2.实现方式:事件风暴与模型确立(用例分析、场景分析和用户旅程分析) 3.用三步来划定…

如何设计一个低代码平台

编者按:近些年来,低代码发展火热,各种低代码平台如雨后春笋纷纷崛起,这些平台各定位不同,优劣不同,用户的选择空间很大。那么,如果用户想从零开始设计一个低代码平台,该如何做呢&…

QT纯代码设计UI界面Demo

目录 一、前言 二、界面 三、源码简析 四、Demo/源码 一、前言 UI的设计方法有几种: ①一种是使用Qt Designer,也就是可视化设计,这在小型项目中常见,优点就是可观简便; ②另一种就是纯代码设计UI,也…

Verilog RTL 代码设计新手上路

1. 做一个4选1的mux,并且进行波形仿真 和2选1的mux对比,观察资源消耗的变化: 实验分析:4选1的mux实际上就是在2选1的mux上进行拓展,选用2位的控制信号控制4位输入信号的选择输出 实验代码设计如下: …

代码设计流程

一、需求分析 1、需求分析的三层境界:实现者、分析者、引导者。 2、在需求中提取到合适的用例(以抽卡系统为例) 3、用例分析法 5W1H分析法 对上面的“抽卡”用例进行分析如下 5W内容What抽取卡牌Who玩家When游戏服务器开启期间Where抽卡…

代码设计的内功——代码设计原则

引言 好代码是设计出来的,也是重构出来的,更是不断迭代出来的。在我们接到需求,经过概要设计过后就要着手进行编码了。但是在实际编码之前,我们还需要进行领域分层设计以及代码结构设计。那么怎么样才能设计出来比较优雅的代码结构…

二维傅里叶变换频谱图的含义

二维傅里叶变换频谱图的含义 在一维傅里叶变换得到的频谱图中,每个点表示其对应的幅度频率与其坐标对应的简谐波。二位傅里叶变换的频谱图,简谐波的振幅由对应点处对应的亮度表示,每一个点表示的波形为其对应的横纵坐标所表示的简谐波的叠加…