摘要

本文深入分析了Linux索引节点缓存的实现

1. Linux inode cache分析

Linux inode cache机制实现在fs/inode.c文件中。

1.1 Inode的slab分配器缓存

索引节点缓存(inode cache,简称icache)机制的实现是以inode对象的slab分配器缓存为基础的,因此要从物理内存中申请或释放一个inode对象,都必须通过kmem_cache_alloc()函数和kmem_cache_free()函数来进行。

Inode对象的slab分配缓存由一个kmem_cache_t类型的指针变量inode_cachep来定义。这个slab分配器缓存是在inode cache的初始化函数inode_init()中通过kmem_cache_create()函数来创建的。

Linux在inode.c文件中又定义了两个封装函数,来实现从inode_cachep slab分配器缓存中分配一个inode对象或将一个不再使用的inode对象释放给slab分配器,如下所示:

#define alloc_inode()

((struct inode *) kmem_cache_alloc(inode_cachep, SLAB_KERNEL))

static void destroy_inode(struct inode *inode)

{

if (!list_empty(&inode->i_dirty_buffers))

BUG();

kmem_cache_free(inode_cachep, (inode));

}

1.2 和inode对象相关的一些底层操作

源文件inode.c中实现了一些对inode对象的底层基本操作,如下:

(1)clean_inode()——初始化部分inode对象成员域该函数用来将一个刚从inode_cachep slab分配器中分配得到的inode对象中的某些成员初始化为已知的值(通常为0),但是有一个例外,既链接数i_nlink被初始化为1。这是一个静态的静态内部函数,因此它只能被inode.c中的其他函数所调用,如:get_empty_inode()和get_new_inode()。

/*

* This just initializes the inode fields

* to known values before returning the inode..

*

* i_sb, i_ino, i_count, i_state and the lists have

* been initialized elsewhere..

*/

static void clean_inode(struct inode *inode)

{

static struct address_space_operations empty_aops;

static struct inode_operations empty_iops;

static struct file_operations empty_fops;

memset(&inode->u, 0, sizeof(inode->u));

inode->i_sock = 0;

inode->i_op = &empty_iops;

inode->i_fop = &empty_fops;

inode->i_nlink = 1; /* NOTE!i_nlink被初始化为1 */

atomic_set(&inode->i_writecount, 0);

inode->i_size = 0;

inode->i_generation = 0;

memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));

inode->i_pipe = NULL;

inode->i_bdev = NULL;

inode->i_data.a_ops = &empty_aops;

inode->i_data.host = inode;

inode->i_mapping = &inode->i_data;

}

(2)get_empty_inode()——从slab分配器中分配一个空的inode对该函数通过调用alloc_inode宏从slab分配器中分配一个inode对象,然后把除了I_count引用计数和链接计数I_nlink之外的所有域都初始化为NULL(部分域的初始化通过调用clean_inode函数来完成),并将这个inode对象链入inode_in_use链表中。最后返回这个inode对象的指针,如下所示:

struct inode * get_empty_inode(void)

{

static unsigned long last_ino;

struct inode * inode;

inode = alloc_inode();

if (inode)

{

spin_lock(&inode_lock);

inodes_stat.nr_inodes++;

list_add(&inode->i_list, &inode_in_use);

inode->i_sb = NULL;

inode->i_dev = 0;

inode->i_ino = ++last_ino;

inode->i_flags = 0;

atomic_set(&inode->i_count, 1);

inode->i_state = 0;

spin_unlock(&inode_lock);

clean_inode(inode);

}

return inode;

}

Linux内核模块通常并不会调用这个函数来分配一个inode对象。那些想获取一个没有索引节点号的inode对象的内核模块(如网络层等),以及那些没有任何已知信息的fs,通常会用这个函数来获取一个新的inode对象。

(3) clear_inode()——清除一个inode对象中的内容在调用destroy_inode()函数释放一个inode对象之前,通常调用该函数来清除该inode对象中内容,如:使inode引用的缓冲区无效、解除对其它对象的引用等。

/**

* clear_inode - clear an inode

* @inode: inode to clear

*

* This is called by the filesystem to tell us

* that the inode is no longer useful. We just

* terminate it with extreme prejudice.

*/

void clear_inode(struct inode *inode)

{

if (!list_empty(&inode->i_dirty_buffers))

invalidate_inode_buffers(inode);

if (inode->i_data.nrpages)

BUG();

if (!(inode->i_state & I_FREEING))

BUG();

if (inode->i_state & I_CLEAR)

BUG();

wait_on_inode(inode);

if (IS_QUOTAINIT(inode))

DQUOT_DROP(inode);

if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->clear_inode)

inode->i_sb->s_op->clear_inode(inode);

if (inode->i_bdev) {

bdput(inode->i_bdev);

inode->i_bdev = NULL;

}

inode->i_state = I_CLEAR;

}

1.3 icache数据结构

Linux通过在inode_cachep slab分配器缓存之上定义各种双向链表来实现inode缓存机制,以便有效地管理内存inode对象。这些链表包括:正在使用的inode链表、未使用的inode链表、inode哈希链表和匿名inode的哈希链表,他们的定义如下:

static LIST_HEAD(inode_in_use);

static LIST_HEAD(inode_unused);

static struct list_head *inode_hashtable;

static LIST_HEAD(anon_hash_chain); /* for inodes with NULL i_sb */

此外,每个超级块对象super_block中还有一条被修改过的、且正在使用的inode双向链表s_dirty。

每一个inode对象都会存在于两个分离的双向链表中:

(1)一个就是inode哈希链表inode_hashtable,用来加快inode查找,每个inode对象都通过I_hash指针链入哈希链表中。

(2)另一个就是inode的“类型”链表:

如果I_count>0、I_nlink>0且该inode不脏,则这个inode就通过其I_list指针链入系统全局的inode_in_use双向链表。

如果I_count和I_nlink都大于0,但是这个inode为脏(既I_state域中设置了I_DIRTY标志),则这个inode通过I_list指针链入他所属的super_block对象的s_dirty链表。

如果I_count=0,则通过其I_list链入inode_unused链表。

对于那些不属于任何超级块对象(即I_sb=NULL)的匿名inode对象,则通过I_hash指针链入系统全局的匿名inode哈希链表anon_hash_chain。

1.3.1 对inode缓存链表的锁保护

Linux在inode.c中定义了自旋锁inode_lock,来实现对所有inode缓存链表的互斥访问。也即,任何访问任意一条inode缓存链表的代码段,都必须通过调用spin_lock()函数持有该自旋锁,并在结束访问后通过spin_unlock()释放该自旋锁。Inode_lock的定义如下: Spinlock_t inode_lock=SPIN_LOCK_UNLOCKED; NOTE!如果要改变一个正在使用的inode对象的I_state域,也必须先持有该自旋锁。

1.3.2 inode缓存的统计信息

全局变量inodes_stat定义了inode cache的统计信息,主要包括cache中的inode对象总数和其中未使用的inode个数,其定义如下:

struct {

int nr_inodes;

int nr_unused;

int dummy[5];

} inodes_stat;

1.3.3 inode哈希链表

inode哈希链表的主要用途是加快在icache中查找一个特定的inode对象。指针inode_hashtable指向一组哈希链表表头,所有哈希函数值(记为h)相同的inode对象都通过I_hash指针作为接口组成双向链表,并挂在inode_hashtable[h]这个哈希链表表头之后。所有哈希链表表头都放在一起组成一个数组,该数组的首地址由指针inode_hashtable所指向。

在Linux中,inode哈希链表表头数组是存放在2order个连续的物理页帧中的,其中,order≥1,且它的值与系统总的物理页帧数num_physpages的值相关。因此,哈希链表表头的个数为:2order*PAGE_SIZE/sizeof(struct list_head)。由于list_head结构类型的大小是8个字节(2个32位指针),因此:inode哈希链表表头的个数可以表示为:2(order+12-3)。

(1)哈希链表的初始化

inode cache的初始化工作是由inode_init()函数来完成的,它主要完成两项工作:(1)inode哈希链表的初始化,包括为inode哈希链表表头数组分配物理内存等;

(2)创建inode slab分配器缓存。该函数的源代码如下:

/*

* Initialize

【责编:admin】

--------------------next---------------------

linux变量inode,Linux inode cache分析相关推荐

  1. 深入理解linux文件系统( 理解inode与block,理解硬链接软链接,掌握恢复误删文件及其分析方法,掌握用户日志及其查询命令 )

    文章目录 深入理解linux文件系统 前言 inode与block详解 inode和bolck概述 1:数据(block)块: 2:元信息 : inode(索引节点) inodu的内容 Linux系统 ...

  2. Linux文件系统中的inode节点详细介绍

    一.inode是什么? 理解inode,要从文件储存说起. 文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector).每个扇区储存512字节(相当于0.5KB). 操作系统 ...

  3. linux 挂载分区inode,Linux中分区挂载和LABEL的指定

    让Linux开机就挂载分区,我知道有两种方法,一种是fstab,另一种是rc.local,我比较倾向前一种. 这两种方法各要注意: fstab是在开机时就挂载,所以你要注意是否你的分区位于某个需要特别 ...

  4. linux 文件inode,linux文件系统-inode学习整理

    linux文件系统-inode学习整理 介绍 linux文件系统可讲的模块有很多,包括文件系统整体架构.文件系统分类.虚拟文件系统以及文件系统存储结构等等,本文主要介绍的是文件系统的存储结构,也就是本 ...

  5. linux文件存储、inode、硬链接、软链接

    目录 介绍 inode的内容 inode的大小 inode号码 目录文件 硬链接 软链接 介绍 文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector).每个扇区储存512 ...

  6. Linux文件系统中的inode

    磁盘中最小的存储单位是"扇区",操作系统中文件最小的存储单位是"块",一个"块"由连续的8个"扇区"组成,一个文件可以由 ...

  7. 以下关于linux文件系统中inode,linux文件系统—inode及相关概念.docx

    linux文件系统-inode及相关概念 linux文件系统-inode及相关概念 博客分类: /category/156693Linux/blogs/tag/LinuxLinux/blogs/tag ...

  8. 【Linux】文件系统与inode、软硬链接

    目录 一.磁盘结构 二.文件系统 2.1 文件系统的区域划分 2.2 文件系统分区介绍 2.3 文件名与inode 三.软硬链接 3.1 软链接 3.2 硬链接 一.磁盘结构 理解文件系统前首先我们要 ...

  9. linux 在线扩inode,linux inode 详解 / 线上inode爆满解决方案

    本文大量参考阮一峰大神博客,整理笔记 之所以写inode文章是由于一次线上问题,引发对inode深入的思考. 磁盘的inode监控与磁盘空间的监控同等重要,线上服务器一定要做好磁盘inode与磁盘空间 ...

最新文章

  1. 这十个好习惯助你摆脱消极的态度
  2. .NetCore下使用Polly结合IHttpClientFactory实现聚合服务
  3. 【英语学习】【WOTD】emote 释义/词源/示例
  4. 【C#编程基础学习笔记】4---Convert类型转换
  5. 前端大神:如何看待 React Server Components?
  6. 四种模式、五大架构 规划企业物联网蓝图
  7. Hybrid APP介绍
  8. java类图_java类图制作 - lxw12138的个人空间 - OSCHINA - 中文开源技术交流社区
  9. css表格一行删除线,EXCEL电子表格一行中间画一条删除线怎么画/excel表格如何划掉数据...
  10. 这是我看过把Spring Cloud核心组件讲的最明白的一个故事了
  11. 全民奇迹修复云服务器跨服,穿过无数服务器来战你《全民奇迹MU》开启跨服PK时代...
  12. 磊科路由器dns服务器老要修复,路由器DNS劫持的解决方法
  13. 销售凭证、客户主数据
  14. 上市十天高管大换血 甘李药业有隐疾?
  15. group_wait、group_interval、repeat_interval对告警的影响
  16. Dijkstra算法求解单源最短路径问题
  17. 全新角度了解百度地图
  18. 进入bios或者安全模式
  19. mac hdmi 不能调整音量_有史以来最贵的苹果Mac笔记本,PowerBook 5300ce(1995)体验...
  20. VueJS 基础之组件

热门文章

  1. css规范(书写顺序)
  2. 有趣的 contentEditable
  3. 2022中国眼博会,山东视力防控展会,近视镜,中国近视矫正展
  4. 「TCG 规范解读」简介-MISC-TPM 工作组
  5. mysql oltp olap_数据库 OLAP、OLTP的介绍和比较
  6. 游离态GLZ的LeetCode刷题笔记2
  7. android5.0联系人铃声设置和来电读取分析
  8. 51Nod 1366 贫富差距
  9. 跟着我做毕设 一起毕业?-----塔吊篇(二)
  10. 模型计算机微指令总表,计算机组成与结构微指令表(总).doc