文件系统之inode
注:本文分析基于linux-4.18.0-193.14.2.el8_2内核版本,即CentOS 8.2
1 inode
内存中,每个文件都有一个inode,一切皆文件,其实应该是说一切皆inode。inode保存了文件系统中一个文件的属性描述,比如文件类型,文件权限,属主,文件创建、读取或修改的时间等等。除了内存中的inode,磁盘中也有对应的inode结构,比如ext4文件系统中,内存中的inode是struct ext4_inode_info,而磁盘中的inode是struct ext4_inode_info,今天我们主要分析下内存中的inode结构。
2 inode主要成员变量
struct inode {umode_t i_mode; //文件类型和访问权限unsigned short i_opflags;kuid_t i_uid; //inode所属文件的所有者idkgid_t i_gid; //inode所属文件所在组idunsigned int i_flags;...const struct inode_operations *i_op; //该inode操作函数集合struct super_block *i_sb; //指向所属超级块对象struct address_space *i_mapping; //指向inode在内存中的pagecache...unsigned long i_ino; //inode节点号 ls -i 可以查看文件inode号...struct timespec64 i_atime; //文件最后访问时间struct timespec64 i_mtime; //文件最后修改时间struct timespec64 i_ctime; //文件创建时间spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */unsigned short i_bytes; //文件在最后一块中的字节数unsigned int i_blkbits; //block size(字节位数),一般为9enum rw_hint i_write_hint;blkcnt_t i_blocks; //文件的总块数,这里一个block为512 byte,也就是扇区大小...unsigned long dirtied_when; //inode变脏的时间unsigned long dirtied_time_when;//通过该变量链接到全局inode哈希表inode_hashtable,用于inode的快速查找//哈希值通过超级块和inode number计算struct hlist_node i_hash; //通过该变量挂载到bdi_writeback的b_io链表,等待BDI回写,也就是这是脏inodestruct list_head i_io_list; /* backing dev IO list *///该inode所在设备对应的bdi_writeback结构,用于inode的回写struct bdi_writeback *i_wb; ...struct list_head i_lru; //通过该变量链接到超级块的s_inode_lru链表struct list_head i_sb_list; //通过该变量链接到超级块的s_inodes上struct list_head i_wb_list; //通过该变量链接到超级块的s_inodes_wb上,回写统计union {//所有引用该inode的目录项将形成一个链表//比如文件被链接到其他的文件,就会有多个dentrystruct hlist_head i_dentry; struct rcu_head i_rcu;};...const struct file_operations *i_fop; //该inode对应的文件的操作函数集合struct file_lock_context *i_flctx;struct address_space i_data; //内嵌在inode的pagecache对象...void *i_private; /* fs or device private pointer */RH_KABI_RESERVE(1)RH_KABI_RESERVE(2)
};
3 创建一个inode
我们以ext4的创建目录——mkdir为例,看下inode的创建过程,
const struct inode_operations ext4_dir_inode_operations = {.create = ext4_create,....mkdir = ext4_mkdir,...
};const struct file_operations ext4_dir_operations = {.llseek = ext4_dir_llseek,.read = generic_read_dir,....open = ext4_dir_open,.release = ext4_release_dir,
};static int ext4_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{...//调用ext4文件系统的alloc_inode函数,创建新的inodeinode = ext4_new_inode_start_handle(dir, S_IFDIR | mode,&dentry->d_name,0, NULL, EXT4_HT_DIR, credits);...//对于目录文件,i_op和i_fop指向的也是对应的目录操作函数//如果是普通文件,i_op和i_fop指向的会是file操作函数inode->i_op = &ext4_dir_inode_operations;inode->i_fop = &ext4_dir_operations;...
}
ext4_new_inode_start_handle通过以下调用路径,
ext4_new_inode_start_handle ->__ext4_new_inode ->new_inode
最终在new_inode中将分配成功的inode挂到对应超级块的s_inodes链表上,这个链表就是这超级块所有的inode对象。
struct inode *new_inode(struct super_block *sb)
{struct inode *inode;spin_lock_prefetch(&sb->s_inode_list_lock);//调用对应文件系统的alloc_inode方法创建一个inodeinode = new_inode_pseudo(sb);if (inode)//将该inode挂载到对应超级块的s_inodes链表上inode_sb_list_add(inode);return inode;
}
4 添加inode到inode cache链表
超级块上除了s_inodes链表,还有一个LRU链表s_inode_lru,这放的是未使用,或者干净的inode,比如回写完毕的inode就会挂载到这个链表上,这个链表也称为inode cache,在系统需要回收内存时,就会对这个链表下手,回收最近最少使用的inode。
添加到s_inode_lru链表的路径主要有两个:
- 回写完毕的inode,也就是干净的inode
- inode没有其他进程引用
不过最终都是通过inode_lru_list_add将inode挂载到s_inode_lru链表,
static void inode_lru_list_add(struct inode *inode)
{//将inode挂载到超级块的s_inode_lru链表if (list_lru_add(&inode->i_sb->s_inode_lru, &inode->i_lru))this_cpu_inc(nr_unused);elseinode->i_state |= I_REFERENCED;
}
先看回写完毕的inode,
inode_sync_complete ->inode_add_lru ->inode_lru_list_add
然后是无其他进程引用时,
iput ->iput_final ->inode_add_lru ->inode_lru_list_add
5 从inode cache中删除inode(回收inode cache)
上面我们提到系统回收内存时,会对操作s_inode_lru链表,我们也大概看下,
long prune_icache_sb(struct super_block *sb, struct shrink_control *sc)
{LIST_HEAD(freeable);long freed;//遍历超级块的s_inode_lru链表,按照回收控制结构sc指定的回收数量,//将可回收的inode隔离到freeable链表中集中回收freed = list_lru_shrink_walk(&sb->s_inode_lru, sc,inode_lru_isolate, &freeable);//将隔离出来的inode进行回收,这样隔离后可以避免锁竞争dispose_list(&freeable);return freed;
}
回收inode主要是要从几个链表中抽离,和脏数据回写
- 超级块的s_inode_lru链表
- bdi_writeback的b_io链表
- 超级块的s_inodes链表
- 回写pagecache
- 全局inode哈希表
static void dispose_list(struct list_head *head)
{while (!list_empty(head)) {struct inode *inode;inode = list_first_entry(head, struct inode, i_lru);//将inode从超级块的s_inode_lru链表摘除list_del_init(&inode->i_lru);//回收inodeevict(inode);cond_resched();}
}static void evict(struct inode *inode)
{const struct super_operations *op = inode->i_sb->s_op;BUG_ON(!(inode->i_state & I_FREEING));BUG_ON(!list_empty(&inode->i_lru));//从bdi_writeback的b_io链表摘除if (!list_empty(&inode->i_io_list))inode_io_list_del(inode);//将inode从超级块的s_inodes链表摘除inode_sb_list_del(inode);//等待该inode回写完毕inode_wait_for_writeback(inode);//调用对应文件系统的evict_inode方法,回写pagecacheif (op->evict_inode) {op->evict_inode(inode);} else {truncate_inode_pages_final(&inode->i_data);clear_inode(inode);}//如果是块设备inodeif (S_ISBLK(inode->i_mode) && inode->i_bdev)bd_forget(inode);//如果是字符型设备if (S_ISCHR(inode->i_mode) && inode->i_cdev)cd_forget(inode);//从全局inode哈希表中摘除remove_inode_hash(inode);...//回收inodedestroy_inode(inode);
}
处理完这些引用后,就可以调用destroy_inode回收到slab缓存,对于ext4,调用的是ext4_destroy_inode,
static void destroy_inode(struct inode *inode)
{BUG_ON(!list_empty(&inode->i_lru));__destroy_inode(inode);//调用对应文件系统的destroy_inode方法,将inode回收到slab缓存//对于ext4,调用的是ext4_destroy_inodeif (inode->i_sb->s_op->destroy_inode)inode->i_sb->s_op->destroy_inode(inode);elsecall_rcu(&inode->i_rcu, i_callback);
}static void ext4_destroy_inode(struct inode *inode)
{ if (!list_empty(&(EXT4_I(inode)->i_orphan))) {...}//调用ext4_i_callback将inode释放会slab缓存call_rcu(&inode->i_rcu, ext4_i_callback);
}static void ext4_i_callback(struct rcu_head *head)
{struct inode *inode = container_of(head, struct inode, i_rcu);//释放回slab缓存kmem_cache_free(ext4_inode_cachep, EXT4_I(inode));
}
6 结构关系
- 一块磁盘,三个分区,sda1和sda2是ext4文件系统,sda3是xfs文件系统
- 全局超级块链表super_blocks将三个超级块串联在一起
- sda1上的ext4_inode_info结构中内嵌inode结构,其中i_sb指向对应的超级块
- A、B、C三个inode挂载到超级块s_nodes链表,A,B两个未使用的inode还会挂载到s_inode_lru链表
- sda2上的ext4文件系统同sda1一样
- 而sda3上的xfs除了对应的xfs_inode结构不同,大体结构也是一样的,这其实就是VFS的作用,对所有文件系统抽象了一层
文件系统之inode相关推荐
- Linux文件系统之inode,block,superblock
文件存储在硬盘上,硬盘的最小存储单位叫做扇区sector,每个扇区存储512个字节(0.5)kb,系统读取文件时不会一个一个扇区的读,而是一次性连续读取多个扇区,即一次性读1个'块'( ...
- 文件系统:inode、entry、superblock
文件系统: inode:记录文件的基本数据信息: dentry(目录项):记录文件的文件名.父目录.子目录等信息 superblock(超级块):每个文件系统都有一个superblock; inode ...
- Linux 文件系统之 inode 概述
inode是一个重要概念,是理解Unix/Linux文件系统和硬盘储存的基础. 我觉得,理解inode,不仅有助于提高系统操作水平,还有助于体会Unix设计哲学,即如何把底层的复杂性抽象成一个简单概念 ...
- Linux文件系统之inode与软硬连接
一.inode是什么? 理解inode,要从文件储存说起. 文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector).每个扇区储存512字节(相当于0.5KB). 操作系统 ...
- [OS-Linux]详解Linux的文件系统、inode和动静态库
本文详解了Linux中的文件系统,包括inode.软连接,硬链接.动静态库. 目录 一.理解文件系统 二.inode 三.硬链接和软连接 1.硬链接 2.软连接 四.动态库和静态库 1. 静态库与动态 ...
- 以下关于linux文件系统中inode,linux文件系统—inode及相关概念.docx
linux文件系统-inode及相关概念 linux文件系统-inode及相关概念 博客分类: /category/156693Linux/blogs/tag/LinuxLinux/blogs/tag ...
- 【Linux】文件系统与inode、软硬链接
目录 一.磁盘结构 二.文件系统 2.1 文件系统的区域划分 2.2 文件系统分区介绍 2.3 文件名与inode 三.软硬链接 3.1 软链接 3.2 硬链接 一.磁盘结构 理解文件系统前首先我们要 ...
- Linux 文件系统与inode,软硬链接
目录 磁盘的结构 磁盘的抽象(虚拟,逻辑)结构 分区 Block Group 块组: 分析: 文件名 vs inode编号 创建/删除/查看 一个文件,操作系统做了什么? 软硬链接 软连接 硬链接 对 ...
- 理解Linux文件系统之 inode
一.inode是什么? 理解inode,要从文件储存说起. 文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector).每个扇区储存512字节(相当于0.5KB). 操作系统 ...
- 【Linux】什么是文件系统及inode?如何创建软硬链接?软硬链接有什么作用?
inode 软硬链接 创建软硬链接 理解硬链接 理解软链接 inode 了解一下文件系统: Linux ext2文件系统,上图为磁盘文件系统图(内核内存映像肯定有所不同),磁盘是典型的块设备,硬盘分区 ...
最新文章
- 皮一皮:我好像知道了什么...
- python读取txt文件并写入excel-Python读excel生成数据存入txt文件
- Linux常用命令 积累
- 在“3_人民日报语料”中统计“日语借词”的词频;
- 开场 Live,分享点干货——「深入了解 Node.js 包与模块机制」
- Windows 7 / Vista 分区问题
- 等级考试(二):二级C++---宏观把控
- vue.js中H5使用微信摇一摇抽奖,判断摇一摇次数
- linux lvs 存储层,LVS集群配置之LVS介绍
- c语言 电阻器的分类,电阻器的分类
- Rust:FFI 编程中的 CStr 和 CString
- C#——NPOI对Excel的操作、导入导出时异常处理(二)
- 硬件探索——数字钟的设计与制作
- 蓝桥杯,基础练习 Fibonacci数列(斐波那契数列) C++
- 【Day3.3】美攻铁道市场零距离接触行驶中的火车
- 用C语言实现求水仙花数
- Project2 分段切割路面,只取一个种子点
- Module and Component
- 【VNC使用指南】Ubuntu Kylin 使用 TigerVNC
- java计算机毕业设计星星电影购票网站源码+mysql数据库+lw文档+系统+调试部署
热门文章
- html 协议 302,http协议301、302的原理和实现
- 大厂高薪校招真 相:逼走老员工
- 服务器内部转发以及客户端重定向概念的学习
- NRF52832 RNG随机数产生器
- Android 源码编译问题总结
- arm linux之data abort异常处理
- python报错UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0x97 in position的解决方法
- ObjectArx块操作封装
- R软件学习笔记—Legend
- 当图网络遇上计算机视觉!计算机视觉中基于图神经网络和图Transformer的方法和最新进展...