innode索引节点

inode 简介

Inode 将系统上每个文件的元数据存储在通常位于分区开头附近的表状结构中。它们存储除文件名和数据之外的所有信息。本质为结构体。也叫作文件属性管理结构,大多数的 inode 都存储在磁盘上。少量常用、近期使用的 inode 会被缓存到内存中。

Linux 通过 inode 节点表将文件的逻辑结构和物理结构进行转换。

给定目录中的每个文件都是一个带有文件名和 inode 编号的条目。通过引用索引节点号从索引节点表中检索有关该文件的所有其他信息。

Inode 编号在分区级别是唯一的。每个分区都有自己的 inode 表。

如果 inode 用完了,即使给定分区上还有剩余空间,也无法创建新文件。

文件的目录通常存放在外存中。目录项(dentry),其本质依然是结构体,重要成员变量有两个 {文件名,inode,…},而文件内容(data)保存在磁盘盘块中。

磁盘高级/逻辑格式化

会把磁盘分为一个一个的分区/卷(分卷Volume)【c盘,d盘,e盘为三个不同的分区】其中每个分区的起始地址、大小等需要用分区表记录。每个分区中可以建立各自独立的文件系统。例如可以在c盘中建立unix文件系统

  • 超级块:迅速找到这个磁盘分区里面所有的空闲块,这样当我们要新建一个文件,给一个文件分配磁盘块的时候,就可以从超级块出发,迅速找到很多很多个/若干个空闲的磁盘块用来分配
  • 位示图(0101):可以迅速判断一个特定的磁盘块此时到底是否空闲
  • i结点区:索引结点,每个文件都有与之对应的索引结点。unix中所有的索引结点都是连续存放在这个i结点区中的,可以认为这个区域是一个超大的数组,而数组的元素就是一个一个的索引结点。因为索引结点连续存放,而且每个索引结点的大小都相同,所以我们可以通过一个索引结点的下标(数组的下标),来迅速定位到一个指定的索引结点。(因为我们知道了所有索引结点的一个起始存放地址以及每个索引结点的大小,再结合上我们要找的那个索引结点的下标,那我们就可以迅速定位到任何一个索引结点所存储的位置。

磁盘高级/逻辑格式化后——文件系统在外存中的布局/结构

文件系统在内存中的结构

分为:目录缓存、系统打开文件表、进程打开文件表

注:

  • 近期访问过的目录文件会缓存在内存中,不用每次都从磁盘读入,这样可以加快目录检索速度。
  • 进程(用户)打开文件表包含在每个进程的PCB进程控制块中。

Linux 中的 inode 是什么?

inode(Index Node)译成中文就是索引节点。虽然历史上对此不太确定,但这是他们提出的最合乎逻辑、最好的猜测。它曾经写成I-node,但连字符随着时间的推移丢失了。

如linfo.org上所述:

inode是一种数据结构…… …… 它存储文件的所有信息,除了文件名和实际数据。

Inode 存储有关它引用的文件的元数据。此元数据包含有关所述文件的所有信息。

  • 文件大小
  • 访问权限
  • 创建时间
  • 修改时间
  • 数据在磁盘的位置
  • 其他信息

inode包含文件的元信息,具体来说有:

  * 文件的字节数

  * 文件的UID

  * 文件的GID

  * 文件的权限

  * 文件的时间戳

  * 链接数,即有多少文件名指向这个inode

  * 文件数据block的位置

其中文件名并不是文件的本身属性,而是文件所在目录的属性,inode中不包含文件名。

补充

文件控制块FCB是用来存放控制文件需要的各种信息的数据结构以实现“按名存取”。FCB的有序集合称为文件目录,一个FCB就是一个文件目录项。一个文件目录也被视为一个文件,称为目录文件

FCB主要包含以下信息:

  • 基本信息,如文件名、文件的物理地址、文件的物理结构等
  • 存取控制信息,包括文件的存取权限,核准用户的存取以及一般用户的存取权限
  • 使用信息,如文件创建时间、上次修改时间等

文件控制块FCB通常存放在(该文件的上级目录的数据盘块)中。

索引节点是对FCB的瘦身

当找到文件名对应的目录项时,才需要将索引结点调入内存,索引结点中记录了文件的各种信息,包括文件在外存中的存放位置,根据“存放位置”即可找到文件。

每个使用的 inode 引用一个文件。每个文件都有一个 inode。目录、字符文件和块设备都是文件。它们每个都有一个 inode。

对于目录中的每个文件,都有一个条目,其中包含文件名和与之关联的索引节点号。

Inode 在分区级别是唯一的。如果两个文件位于不同的分区上,则它们可以具有相同的 inode 编号。Inodes 信息存储在每个分区的战略部分的类似表的结构中,通常在开头附近找到。

如何在 Linux 中查看 inode?

您可以使用以下命令轻松列出 inode 编号:

ls -i

每个文件系统拥有的 inode 数量是在创建文件系统时决定的。对于大多数用户来说,默认的 inode 数量已经足够了。

创建文件系统时的默认设置是每 2K 字节空间创建 1 个索引节点。这为大多数系统提供了大量 inode。在用完 inode 之前,您很可能会用完空间。如果需要,您可以在创建文件系统时指定要创建多少 inode。

如果您用完 inode,您将无法创建新文件。您的系统也将无法这样做。大多数用户不会遇到这种情况,但这是可能的。

例如,邮件服务器会存储大量非常小的文件。许多这些文件将小于 2K 字节。它也有望不断增长。因此,邮件服务器有可能在空间用完之前用完 inode。

一些文件系统,如Btrfs、JFS、 XFS 已经实现了动态索引节点。如果需要,他们可以增加可用的 inode 数量。

索引节点是如何工作的?

创建新文件时,会为其分配一个 inode 编号和文件名。inode 编号是该文件系统中的唯一编号。名称和 inode 编号都作为条目存储在目录中。

当我运行ls 命令“ ls -li / ”时,文件名和 inode 编号是存储在目录/中的内容。使用 inode 编号从 inode 表中检索剩余信息用户、组、文件权限、大小等。

 文件系统在打开一个文件时,要做的有

1.系统找到这个文件名对应的inode:在目录表中查找该文件名对应的项,由此得到该文件相对应的 inode 号

2.通过inode号,获取到磁盘中的inode信息,其中最重要的内容是磁盘地址表

3.通过inode信息中的磁盘地址表,文件系统把分散存放的文件物理块连接成文件的逻辑结构。在磁盘地址表中有 13 个块号,文件将以块号在磁盘地址表中出现的顺序依次读取相应的块。找到文件数据所在的block,读出数据。

根据以上流程,我们可以发现,inode应该是有一个专门的存储区域的,以方便系统快速查找。事实上,一块磁盘创建的时候,操作系统自动将硬盘分成两个区域:存放文件数据的数据区,与存放inode信息的inode区(inode table)。

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

也就是说,每个分区的inode总数从格式化之后就固定了,因此有可能会出现存储空间没有占满,但因为小文件太多而耗尽了inode的情况。这个时候就只能清除inode占用高的文件或者目录或修改inode数量了,当然,inode的调整需要重新格式化磁盘,需要确保数据已经得到有效备份后,再进行此操作。

这时候又产生了新的问题:文件创建时要为文件分配哪一个inode号呢?即如何保证分配的inode号没有被占用?
既然是"是否被占用"的问题,使用位图是最佳方案,像bmap记录block的占用情况一样。标识inode号是否被分配的位图称为inodemap简称为imap。这时要为一个文件分配inode号只需扫描imap即可知道哪一个inode号是空闲的。

(位图法就是bitmap的缩写。所谓bitmap,就是用每一位来存放某种状态,适用于大规模数据,但数据状态又不是很多的情况。)

类似bmap块位图一样,inode号是预先规划好的。inode号分配后,文件删除也会释放inode号。分配和释放的inode号,像是在一个地图上挖掉一块,用完再补回来一样。

imap存在着和bmap和inode table一样需要解决的问题:如果文件系统比较大,imap本身就会很大,每次存储文件都要进行扫描,会导致效率不够高。同样,优化的方式是将文件系统占用的block划分成块组,每个块组有自己的imap范围,以减少检索时间。

索引节点和软/硬链接

软链接或符号链接是 Linux 的一个众所周知的功能。但是,当您在 Linux 中创建符号链接时,Inode 会发生什么情况?在下一张图片中,我有一个名为“ dir1 ”的目录,一个名为“ file1 ”的文件,在“ dir1 ”中我有一个名为“ slink1 ”的软链接,它指向“ ../file1 ”

正如预期的那样,dir1 和 file1 具有不同的 inode 编号。而且软链接也是如此。创建软链接时,您创建了一个新文件。在其元数据中,它指向目标。对于您创建的每个软链接,您都使用一个 inode。

使用ln 命令在 dir1 中创建硬链接后:

您可以看到“ file1”和“ hlink1 ”具有相同的 inode 编号。说实话,由于索引节点,硬链接成为可能。硬链接不会创建新文件。它只是为相同的数据提供了一个新名称。

在旧版本的 Linux 中,可以硬链接目录。甚至可以让给定的目录成为它自己的父目录。由于 inode 实现,这成为可能。这现在受到限制,以防止用户创建非常混乱的目录结构。

inode 的其他含义

inode 的工作方式也是不可能在不同文件系统之间创建硬链接的原因。允许这样的任务将打开 inode 编号冲突的可能性。另一方面,可以跨不同的文件系统创建软链接。

因为硬链接和原文件有相同的inode号,你可以删除原文件,数据仍然可以通过硬链接访问。在这种情况下,您所做的只是删除指向该 inode 编号的名称之一。链接到此 inode 编号的数据将保持可用,直到删除与其关联的所有名称。

索引节点也是 Linux 系统无需重启即可更新的重要原因。这是因为一个进程可以使用库文件,而另一个进程可以用新版本替换该文件。因此,为新文件创建一个新的 inode。已经运行的进程将继续使用旧文件,而每次对其进行新调用都会导致使用新版本。

inode 附带的另一个有趣的特性是能够将数据存储在 inode 本身中。这称为内联。这种存储方法具有节省空间的优点,因为不需要数据块。它还通过避免更多的磁盘访问来获取数据来增加查找时间。

某些文件系统(如 ext4)有一个名为 inline_data 的选项。启用后,它允许操作系统以这种方式存储数据。由于大小限制,内联仅适用于非常小的文件。ext2 及以后的版本经常会这样存储软链接信息。也就是说,如果大小不超过 60 字节。

系统对文件的操作会可能影响inode

复制:创建一个包含全部数据与新inode号的新文件

移动:在同一磁盘下移动时,所在目录改变,node号与实际数据存储的块的位置都不会变化。跨磁盘移动当然会删除本磁盘的数据并创建一条新的数据在另一块磁盘中。

硬链接: 同一个inode号代表的文件有多个文件名,即可以用不同的文件名访问同一份数据,但是它们指向的inode编号是相同的,并且文件元数据中链接数会增加。不可以对目录创建硬链接。

软链接: 软链接的本质是一个链接文件,其中存储的了对另一个文件的指针(存放目标文件路径)。所以对一个文件创建软链接,inode号不相同,创建软链接文件的链接数不会增加。可以对目录创建软链接。

删除:当删除文件时,会先检查inode中的链接数。如果链接数大于1,就只会删掉一个硬链接,不影响数据。如果链接数等于1,那么这个inode就会被释放掉,对应的inode指向的块也会被标记为空闲的(数据不会被置零,所以硬盘数据被误删除后,若没有新数据写入可恢复)。如果是软链接,原文件被删除后链接文件就变成了悬挂链接(dangling link),无法正常访问了。

利用inode还可以删除一些文件名中有转义字符或控制字符的文件,最典型的就是开头为减号-的文件。这种无法直接用rm命令来搞,就可以先查出它们的inode编号再删除: find ./ -inum 10086 -exec rm {} \:

最后:

  • 进程内打开文件表在内存,不是外存。在Unix操作系统中,每个进程会被分配一个文件描述符表,用于追踪该进程打开的所有文件以及各自的属性。文件描述符表是分配在该进程的内存中的,因此可以说进程内打开文件表在内存中。
  • 进程打开文件的描述符表在PCB中
  • PCB常驻内存
  • 操作系统中的 PCB(Process Control Block,即进程控制块)通常被存储在内存中。每个进程都有一个对应的 PCB,用于存储该进程的各种信息,如进程状态、程序计数器、寄存器值、调度信息、内存分配信息等。在多任务操作系统中,CPU 会定期地进行上下文切换,从而在不同的进程之间进行切换。在每次切换时,CPU 会根据当前进程的 PCB 来保存其状态,并载入下一个进程的状态,以确保运行的程序状态和数据不会丢失。因此,PCB 存储在内存中,可以通过特定的地址或指针来访问。
  • 从冯诺依曼结构的角度来说,必须在内存中,CPU想要执行的指令和要读写的数据,都必须放在内存中,外存虽然跟内存只差一个字,但它们本质天差地别,内存是存储器,硬盘是IO。PCB是内核用来表示进程状态的一个变量,本质上还是数据。

关于 Linux 中的索引节点 Inode,你需要知道的一切-linux索引inode详解

inode:linux的文件存储方式 - 知乎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值