了解Linux文件系统中的索引节点 (linux 索引节点)

Linux是一款十分受欢迎的操作系统,它具有开放源代码、安全稳定、高自由度等优点。其中Linux文件系统是操作系统中重要的一部分,它负责对文件进行管理。在Linux文件系统中,每个文件都有一个对应的独特的索引节点(inode),它存储了文件的所有属性和元数据信息。本文将详细介绍Linux文件系统中的索引节点,包括索引节点的创建、结构和使用方法等。

1. 索引节点的创建

在Linux文件系统中,每个文件都有一个对应的索引节点,它由操作系统自动创建并分配。当我们创建一个新文件时,操作系统会为该文件分配一个空闲的索引节点,并将该节点与文件进行关联。索引节点包含了文件的所有属性和元数据信息,它们与文件本身是分离的,因此即使文件的属性和元数据信息发生变化,索引节点却不会改变。

2. 索引节点的结构

索引节点是一个数据结构,它包含了文件的所有属性和元数据信息。下面是一个典型的Linux索引节点结构:

struct inode {

struct hlist_node i_hash;

struct list_head i_list;

struct list_head i__list;

union {

struct hlist_head i_dentry;

struct rcu_head i_rcu;

} i_u;

struct kobject i_kobj;

unsigned long i_ino;

atomic_t i_count;

umode_t i_mode;

unsigned int i_nlink;

uid_t i_uid;

gid_t i_gid;

struct timespec i_atime;

struct timespec i_mtime;

struct timespec i_ctime;

struct inode_operations *i_op;

struct super_block *i_;

spinlock_t i_lock;

unsigned short i_bytes;

unsigned int i_flags;

union {

struct address_space *i_mapping;

void *i_private;

} i_data;

struct list_head i_devices;

struct pipe_inode_info *i_pipe;

struct block_device *i_bdev;

struct cdev *i_cdev;

__u32 i_generation;

__u32 i_fsnotify_mask;

struct mutex i_mutex;

void *i_mutex_refcount;

};

以上结构体不全部解释,但也暂不难看出,在Linux索引节点中存储了如下属性:

– i_mode: 文件类型和权限信息

– i_nlink: 链接计数器(也就是有多少文件名链接指向该文件)

– i_uid: 文件所有者的用户ID

– i_gid: 文件所属组的ID

– i_size: 文件大小

– i_atime: 最后访问时间

– i_mtime: 最后修改时间

– i_ctime: 最后改变时间

– i_blocks: 文件占用块数

– i_data: 文件的数据指针

– i_: 文件所在的超级块

– i_op: inode操作函数

– 等等

3. 索引节点的使用

索引节点是Linux文件系统中最基本的数据结构之一,它存储了文件的所有属性和元数据信息,因此在操作文件时,索引节点非常重要。以下是一些与索引节点相关的操作:

1. 获取文件信息

我们可以使用stat或者fstat系统调用来获取文件的信息。它们会返回一个结构体,该结构体中包含了文件的所有属性和元数据信息。例如,以下是使用stat系统调用获取文件信息的示例:

#include

#include

#include

int mn(int argc, char *argv[]) {

struct stat s;

if(stat(argv[1], &s) == 0) {

printf(“File size: %lld\n”, (long long)s.st_size);

printf(“Number of links: %d\n”, s.st_nlink);

printf(“Last access time: %lld\n”, (long long)s.st_atime);

printf(“Last modification time: %lld\n”, (long long)s.st_mtime);

printf(“Last change time: %lld\n”, (long long)s.st_ctime);

}

}

2. 修改文件信息

如果我们想要修改某个文件的属性或元数据信息,我们可以使用chmod、chown或utime系统调用来实现。例如,以下是使用chmod修改文件权限的示例:

chmod(“testfile”, 0644);

以上语句将文件”testfile”的权限设置为rw-r–r–。

3. 删除文件

当我们删除一个文件时,操作系统会删除该文件对应的索引节点。如果该文件还有其他链接指向它,那么只会删除文件名,而文件本身并不会被删除。当所有链接都被删除后,该文件对应的索引节点将被释放,文件占用的存储空间也将被释放。

相关问题拓展阅读:

linux kernel 文件系统编程接口

进程读写文件之前需要

打开文件

,得到

文件描述符

,然后

通过文件描述符读写文件

.

内核提供了两个打开文件的系统调用

open

openat

.

打开文件的主要步骤如下:

(1)需要

在父目录的数据中查找文件对应的目录项

,

从目录项得到索引节点的编号,然后在内存中创建索引节点的副本

.因为各种文件系统类型的物理结构不同,所以需要提供索引节点操作的

lookup

方法和文件操作的

open

方法.

(2)需要分配文件的一个打开实例–

file

结构体,关联到文件的索引节点.

(3)在进程的打开文件表中

分配一个文件描述符

,

把文件描述符和打开实例的映射添加到进程的打开文件表

中.

进程可通过使用系统调用

close

关闭文件.

系统调用close的执行流程如下:

(1)解除打开文件表和file实例的关联.

(2)在close_on_exec位图中清楚文件描述符对应的位.

(3)释放文件描述符,在文件描述符位图中清除文件描述符对应的位.

(4)调用函数fput释放file实例:把引用计数减1,如果引用计数是0,那么把file实例添加到链表delayed_fput_list中,然后调用延迟工作项delayed_fput_work.

延迟工作项delayed_fput_work的处理函数是flush_delayed_fput,遍历链表delayed_fput_list,针对每个file实例,调用函数__fput来加以释放.

创建不同类型的文件,需要使用不同的命令.

(1)

普通文件

:touch

FILE

,这条命令本来用来更新文件的访问时间和修改时间,如果文件不存在,创建文件.

(2)

目录

:mkdir

DIRECTORY

.

(3)

符号链接(软链接)

:ln -s

TARGET LINK_NAME

或ln –symbolic

TARGET LINK_NAME

.

(4)

字符或块设备文件

:mknod

NAME TYPE

.

(5)

命名管道

:mkpipe

NAME

.

(6)

硬连接

:命令”ln

TARGET LINK_NAME

“.给已经存在的文件增加新的名称,文件的索引节点有一个硬链接计数,如果文件有n个名称,那么硬链接计数是n.

创建文件需要在文件系统中

分配一个索引节点

,然后

在父目录的数据伏猛拆中增加一个目录项来保存文件的名称和索引节点编号

.

删除文件的命令如下:

(1)删除任何类型文件:unlink

FILE

.

(2)rm

FILE

,默认不删除目录,如果使用”-r””-R”或”-recursive”,可以删除目录和目录的内容.

(3)删除目录:rmdir

DICTIONARY

.

内核提供了unlink,unlinkat用来删除文件的名称,如果文件的硬链接计数变成0,并且没有进程打开这个文件,那么删除文件.提供了rmdir删除目录.

删除文件需要从父目录的数据中删除文件对应的目录项,

把文件的索引节点的硬链接计数减1(一个文件可以有多个名称,Linux把文件名称称为硬链接),如果索引节点的硬链接计数变成0,那么释放索引节点

.因为各种文件系统的物理结构不同,所以需要提供索引节点操作的

unlink

方法.

设置文件权限的命令如下:

(1)chmod

… MODE… FILE…

mode : 权限设定字串,格式…>

其中:

(2)chmod

… OCTAL-MODE FILE…

参数OCTAL-MODE是八进制数值.

系统调用chmod负责修改文件权限.

修改文件权限需要修改文件的索引节点的文件模式字段,文件模式字段包含文件类型和访问权限.因为各种文件系统类型的索引节点不同,所以需要提供索引节点操作的

setattr

方法.

访问外部存储设备的速度很慢,为了避免每次读写文件时访问外部存储设备,

文件系统模块为知灶每个文件在内存中创建一个缺枣缓存

,因为

缓存的单位是页

,所以称为

页缓存

.

(1)

索引节点的成员i_mapping

指向地址空间结构体(address_space).进程在打开文件的时候,

文件打开实例(file结构体)的成员f_mapping

也会指向文件的地址空间.

(2)每个文件有一个地址空间结构体

address_space

,成员

page_tree

的类型是结构体radix_tree_root:成员

gfp_mask是分配内存页的掩码,成员rnode指向基数树的根节点

.

(3)使用基数树管理页缓存,把文件的页索引映射到内存页的页描述符.

每个文件都有一个地址空间结构体address_space,用来建立数据缓存(在内存中为某种数据创建的缓存)和数据来源(即存储设备)之间的关联.结构体address_space如下:

地址空间操作结合address_space_operations的主要成员如下:

页缓存的常用操作函数如下:

(1)函数find_get_page根据文件的页索引在页缓存中查找内存页.

(2)函数find_or_create_page根据文件的页索引在页缓存中查找内存页,如果没有找到内存页,那么分配一个内存页,然后添加到页缓存中.

(3)函数add_to_page_cache_lru把一个内存页添加到页缓存和LRU链表中.

(4)函数delete_from_page_cache从页缓存中删除一个内存页.

进程读文件的方式有3种:

(1)调用内核提供的

读文件的系统调用

.

(2)调用glibc库封装的读文件的

标准I/O流函数

.

(3)创建基于文件的内存映射,把

文件的一个区间映射到进程的虚拟地址空间,然后直接读内存

.

第2种方式在用户空间创建了缓冲区,能减少系统调用的次数,提高性能.第3种方式可以避免系统调用,性能更高.

读文件的主要步骤如下:

(1)调用具体文件系统类型提供的文件操作的read和read_iter方法来读文件.

(2)

read或read_iter方法根据页索引在文件的页缓存中查找页,如果没有找到,那么调用具体文件系统类型提供的地址空间的readpage方法来从存储设备读取文件页到内存中

.

为了提高读文件的速度,从存储设备读取文件页到内存中的时候,除了读取请求的文件页,还会预读后面的文件页.如果进程按顺序读文件,预读文件页可以提高读文件的速度;如果进程随机读文件,预读文件页对提高读文件的速度帮助不大.

进程写文件的方式有3种:

(1)调用内核提供的

写文件的系统调用

.

(2)调用glibc库封装的写文件的

标准I/O流函数

.

(3)创建基于文件的内存映射,把

文件的一个区间映射到进程的虚拟空间,然后直接写内存

.

第2种方式在用户空间创建了缓冲区,能够减少系统调用的次数,提高性能.第3种方式可以避免系统调用,性能更高.

写文件的主要步骤如下:

(1)调用具体文件系统类型提供的文件操作的write或write_iter方法来写文件.

(2)write或write_iter方法调用文件的地址空间操作的

write_begin

方法,

在页缓存查找页,如果页不存在就分配页;然后把数据从用户缓冲区复制到页缓存的页中

;最后调用文件的地址空间操作的

write_end

方法.

进程写文件时,内核的文件系统模块把数据写到文件的页缓存,没有立即写回到存储设备.文件系统模块会定期把脏页写回到存储设备,进程也可以调用系统调用把脏页强制写回到存储设备.

管理员可以执行命令”sync”,把内存中所有修改过的文件元数据和文件数据写回到存储设备.

内核提供了

sync

,

syncfs

,

fsync

,

fdatasync

,

sync_file_range

等系统调用用于文件写回.

把文件写回到存储设备的时机如下:

(1)周期回写.

(2)当脏页的数量达到限制的时候,强制回写.

(3)进程调用sync和syncfs等系统调用.

对于类似内存的块设备,例如NVDIMM设备,不需要把文件从存储设备复制到页缓存.DAX绕过页缓存,直接访问存储设备,对于基于文件的内存映射,直接把存储设备映射到进程的虚拟地址空间.

调用系统调用mmap创建基于文件的内存映射,把文件的一个区间映射到进程的虚拟地址空间,这会调用具体文件系统类型提供的文件操作的mmap方法.mmap方法针对设置了标志位S_DAX的索引节点,处理方法如下:

(1)给虚拟内存区域设置标志位VM_MIXEDMAP和VM_HUGEPAGE.

关于linux 索引节点的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » 了解Linux文件系统中的索引节点 (linux 索引节点)