inode 原理解析

文件系统除了文件内容(file content)之外,还依赖于描述这些文件的数据结构(data structures),即元数据metadata。每个文件都会分配一个inode,每个inode都有一个编号inode number。

Inode存储了文件相关信息,如必备属性(by POSIX):    *   Size    *   DeviceID    *   UserID    *   GroupID    *   file access mode:文件类型及拥有者owner、群组group、其他人对文件的操作权限    *   Timestamps:atime(access time),ctime(change time),mtime(modify time)    *   link count:统计指向文件的硬链接(hard links)数量    *   Pointers:指向磁盘上存储文件内容的数据库块(blocks)地址上述信息可以用 stat 命令获取文件的inode号及inode中的信息,即该文件的状态描述信息。
[root@centos7 testdir]# stat aa
  File: ‘aa’
  Size: 0         	Blocks: 0          IO Block: 4096   regular empty file
Device: 805h/2053d	Inode: 131         Links: 1Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: unconfined_u:object_r:etc_runtime_t:s0
Access: 2016-07-30 14:16:14.343586884 +0800Modify: 2016-08-01 16:44:29.000000000 +0800Change: 2016-07-30 14:17:58.446580298 +0800
 Birth: -
通过df -i 命令可以查看每个硬盘分区的inode 总数和已经使用的数量。
[root@centos7 testdir]# df -iFilesystem        Inodes  IUsed     IFree IUse% Mounted on
/dev/sda2      104857600 120034 104737566    1% /
devtmpfs          229977    389    229588    1% /dev
tmpfs             233586      7    233579    1% /dev/shm
tmpfs             233586    560    233026    1% /run
tmpfs             233586     13    233573    1% /sys/fs/cgroup
/dev/sda5       20971520     11  20971509    1% /testdir
/dev/sda1         204800    330    204470    1% /boot
tmpfs             233586     21    233565    1% /run/user/0/dev/sr0               0      0         0     - /run/media/root/CentOS 7 x86_64
在实际中可能会遇到磁盘满了的警告,此时应同时使用 df -i 和 df -h 命令来查看原因究竟是inode达到上限还是空间不足导致的。

wKioL1eehlfTltFBAAAIM2ONW70232.gif

通过 ls -i 命令可以查看每个文件/目录的inode num等。

wKiom1eehnHB2XUtAADcUe7PDNQ415.png

在很多系统中,inode number在系统初建时就有一个固定的最大值,这也限制了文件系统的文件数量。通常inode大概会暂用1%的磁盘空间。

inode number 是磁盘确定位置上存储的inode table的索引。通过inode number,内核驱动可以获取inode存储的内容,包括文件存储位置。

说明:
    *   inode 不存储文件名,仅包含上述其他元数据metadata
    *   目录 实际上是一个复合结构的映射列表,其中每条信息都包含了 filename 及其对应的 inode number
    *   驱动 先到文件夹中找到 filename,再将 filename 转换为inode number
    *   每个分区有自己独立inode table,因此inode num在不同的磁盘分区上是可重复的,但在同一分区内是唯一的

inode的结构和工作模式如下:
In the past, the structure may have consisted of eleven or thirteen pointers, but most modern file systems use fifteen pointers. These pointers consist of (assuming 15 pointers in the inode):
    *   Twelve pointers that directly point to blocks of the file's data (direct pointers)
    *   One singly indirect pointer (a pointer that points to a block of pointers that then point to blocks of the file's data)
    *   One doubly indirect pointer (a pointer that points to a block of pointers that point to other blocks of pointers that then point to blocks of the file's data)
    *   One triply indirect pointer (a pointer that points to a block of pointers that point to other blocks of pointers that point t

wKioL1eehpnCx3PCAAC_zKCWKAY535.png

cp & inode

1. 执行cp命令时,系统会找到一个可用的inode number,然后将数据写入到inode table 
2. 新增一个目录项,将文件名映射到inode number上 
3. 当inode number和inode table处理好了之后,系统才会将文件内容复制到新增的文件中

rm & inode

1. 系统会减去文件的link count数字,然后将对应的inode number标记为可使用
    例如:aa 的 link count=1,当rm -rf aa后,aa 的 link count=0,其所对应的inode number也被回收标为可用2. 文件数据使用的block也会打上可以使用的“标签”(在blockgroup的bitmap中标识为1)3. 移除文件名称和目录项
注意:
    rm并不会真正删除数据,仅当有新的内容写入或格式化磁盘时,数据块中的数据才会丢失。

mv & inode

  • 同一分区:不影响inode table(除了Timestamps)和 blocks,数据不移动

  1. 创建新的目录项,增加新的文件名与inode的映射关系

  2. 删除原有映射关系的目录项

不同分区:相当于cp & rm

软连接(symbolic link)

符号连接(软连接)指向了另一个文件,其本身有单独的inode num。(内部机制如何待查!)

特性:    1. 可跨分区创建软连接;    2. 可对目录创建软连接;    3. 修改/查看软连接,都实际上操作的是软连接指向的源文件;    4. 不会导致源文件 link count 的变化;

创建:    cp -s source dest    ln -s source dest

硬连接(hard link)

硬连接是有着 相同inode number 和 不同filename 的文件。

特性:    1. 文件有相同的 inode 及 data block;    2. 只能对已存在的文件进行创建;    3. 不能跨分区或驱动器创建硬链接(因为每个独立分区有自己独立的inode table);    4. 不能对目录进行创建,只可对文件创建;    5. 删除一个硬链接文件并不影响其他有相同 inode number的文件;    6. 创建后,源文件和硬连接文件的link count都增加;    7. 硬连接的文件类型表现为普通文件;    8. 修改硬连接/源文件内容后,查看任何一个都能看到修改;
    
创建:
    link filename linkname 
    ln   filename linkname

file 检查文件类型

  • 语法

    file [options...] [file...]

  • 参数说明

-b列出文件辨识结果时,不显示文件名称。
-c详细显示指令执行过程,便于排错或分析程序执行
-f列出文件中文件名的文件类型
-F使用指定分隔符号替换输出文件名后默认的”:”分隔符
-i输出mime类型的字符串
-L查看对应软链接对应文件的文件类型
-z尝试去解读压缩文件的内容
  • 示例

[root@centos7 testdir]# file -b aaASCII text

[root@centos7 testdir]# file -c aacont	offset	type	opcode	mask	value	desc

[root@centos7 testdir]# echo /root > aa[root@centos7 testdir]# file -f aa/root: directory
[root@centos7 testdir]# file -F "@" aaaa@ ASCII text

[root@centos7 testdir]# file -i aaaa: text/plain; charset=us-ascii

[root@centos7 testdir]# file dddd: symbolic link to `aa'
[root@centos7 testdir]# file -L dddd: ASCII text

参考文档

  1. 理解 Linux 的硬链接与软链接

  2. inode

  3. inode pointer structure

  4. inode、block