热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

Linuxinodecache机制分析

文章标题:Linuxinodecache机制分析。Linux是中国IT实验室的一个技术频道。包含桌面应用,Linux系统管理,内核研究,嵌入式系统和开源等一些基本分类

  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的“类型”链表:
  l 如果I_count>0、I_nlink>0且该inode不脏,则这个inode就通过其I_list指针链入系统全局的inode_in_use双向链表。
  l 如果I_count和I_nlink都大于0,但是这个inode为脏(既I_state域中设置了I_DIRTY标志),则这个inode通过I_list指针链入他所属的super_block对象的s_dirty链表。
  l 如果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 the hash tables.
  */
  void __init inode_init(unsigned long mempages)
  {
  struct list_head *head;
  unsigned long order;
  unsigned int nr_hash;
  int i;
  
  /*计算order的值,但是我不知道为什么要这样计算?:) */
  mempages >>= (14 - PAGE_SHIFT);
  mempages *= sizeof(struct list_head);
  for (order = 0; ((1UL
推荐阅读
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • Linuxchmod目录权限命令图文详解在Linux文件系统模型中,每个文件都有一组9个权限位用来控制谁能够读写和执行该文件的内容。对于目录来说,执行位的作用是控制能否进入或者通过 ... [详细]
  • 近年来,大数据成为互联网世界的新宠儿,被列入阿里巴巴、谷歌等公司的战略规划中,也在政府报告中频繁提及。据《大数据人才报告》显示,目前全国大数据人才仅46万,未来3-5年将出现高达150万的人才缺口。根据领英报告,数据剖析人才供应指数最低,且跳槽速度最快。中国商业结合会数据剖析专业委员会统计显示,未来中国基础性数据剖析人才缺口将高达1400万。目前BAT企业中,60%以上的招聘职位都是针对大数据人才的。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文主要讨论了在xps15上安装双系统win10和MacOS后,win10无法正常更新的问题。分析了可能的引导问题,并提供了解决方法。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 本文介绍了在Hibernate配置lazy=false时无法加载数据的问题,通过采用OpenSessionInView模式和修改数据库服务器版本解决了该问题。详细描述了问题的出现和解决过程,包括运行环境和数据库的配置信息。 ... [详细]
  • 树莓派Linux基础(一):查看文件系统的命令行操作
    本文介绍了在树莓派上通过SSH服务使用命令行查看文件系统的操作,包括cd命令用于变更目录、pwd命令用于显示当前目录位置、ls命令用于显示文件和目录列表。详细讲解了这些命令的使用方法和注意事项。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • Python语法上的区别及注意事项
    本文介绍了Python2x和Python3x在语法上的区别,包括print语句的变化、除法运算结果的不同、raw_input函数的替代、class写法的变化等。同时还介绍了Python脚本的解释程序的指定方法,以及在不同版本的Python中如何执行脚本。对于想要学习Python的人来说,本文提供了一些注意事项和技巧。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了在Linux下安装Perl的步骤,并提供了一个简单的Perl程序示例。同时,还展示了运行该程序的结果。 ... [详细]
author-avatar
Jaaaaasonnv_116
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有