Xv6内核分析(十六)

gewenbin
gewenbin
gewenbin
188
文章
15
评论
2020年12月20日18:42:09 评论 637

inode分析

1. inode介绍

在xv6中用Inode表示一个文件,inode数据结构在磁盘上和内存中都有表示。磁盘上的inode信息用于表示文件的大小、类型、文件数据在磁盘上的位置等等,内存中的Inode信息用于系统运行时inode的管理和同步。

所有的磁盘上的 inode都被打包在一个称为inode块的连续区域中。每一个 inode的大小都是一样的,所以对于一个给定的数字n,很容易找到磁盘上对应的 inode。事实上这个给定的数字就是操作系统中 inode的编号。

磁盘上的inode由结构体 dinode定义。type 域用来区分文件、目录和特殊文件的inode。如果 type 是0的话就意味着这是一个空闲的inode。nlink 域用来记录指向了这一个inode的目录项,这是用于判断一个 inode是否应该被释放的。size 域记录了文件的字节数。addrs 数组用于这个文件的数据块的块号。

2. icache数据结构

xv6系统通过icache数据结构来管理inode:

Xv6内核分析(十六)

NINODE默认是50,struct inode就是Inode在内存中的表示,其详细结构如下:

Xv6内核分析(十六)

struct inode的下半部就是磁盘上的inode的拷贝。磁盘上的inode用struct dinode表示:

Xv6内核分析(十六)

3. iinit函数

iinit在系统启动的时候被调用,主要功能是初始化icache数据结构和读取磁盘上的超级块到内存中。超级块中含有磁盘上inode的数量和起始扇区号:

Xv6内核分析(十六)

4. ialloc函数

ialloc用于在磁盘上寻找一个空闲的Inode,并返回此inode在内存中的表示:

Xv6内核分析(十六)

IBLOCK的功能是:根据inode的编号计算该inode在磁盘中的扇区号:

Xv6内核分析(十六)

  • 遍历磁盘上所有的inode,找出一个空闲的inode。
  • IPB表示一个扇区中最大能容纳的inode个数,i/IPB表示inode相对于起始Inode扇区的偏移值,再加上超级块中记录的inode起始扇区号,得出的值就表示一个Inode在磁盘中的扇区号。首先读取inode所在的扇区内容到buffer cache中。
  • 然后通过(struct dinode*)bp->data + inum%IPB得到inode在磁盘上的数据结构信息。
  • Inode的类型如果为0表示此Inode空闲,如果不是0,则读取下一个inode进行判断。如果找到空闲的inode,首先将inode结构清零,然后记录要申请的inode的类型,接着通过调用log_write将修改后的inode信息写回磁盘。
  • 通过iget返回inode在内存的数据结构。

4.1 iget函数

iget遍历icache寻找一个指定设备和inode号的活动中的项(ip->ref > 0)。如果它找到一项,它就返回对这个 inode的引用。在 iget 扫描的时候,它会记录扫描到的第一个空闲的icache,之后如果需要可以用这个空槽来分配一个新的icache。

Xv6内核分析(十六)

  • 首先在icache中寻找此inode是否已经存在,判断的条件是inode的引用计数大于0、设备号相同并且inode的编号相同。如果找到符合条件的则将icache中的Inode的引用计数加1,然后返回此icache中的Inode。
  • 如果inode的引用计数为0则表示此icache中的inode是空闲的。
  • 如果在Icache中没有找到对应的inode并且Icache中的Inode有空闲的,则初始化此空闲的Inode。注意,这时Inode的valid成员还是为0状态,iget函数返回的也只是一个可用的icache中的inode。

5. ilock函数

调用者在读写inode的元数据或内容之前必须用 ilock 锁住 inode。一个典型的inode的使用场景如下:

Xv6内核分析(十六)

iget 返回inode可能没有任何有用的内容。为了保证它持有一个磁盘上 inode的有效拷贝,程序必须调用ilock。它会锁住 inode(从而其他进程就无法使用它)并从磁盘中读出inode的信息(如果它还没有被读出的话)。

Xv6内核分析(十六)

  • inode的锁是睡眠锁,这样获取失败,当前进程会一直阻塞直到被唤醒。
  • 如果inode中的valid为0,表示此Inode是从icache分配出来的空闲inode,这时就需要从磁盘上读取inode的信息到Icache中的inode中,然后将valid更新为1。

可以看出ilock的功能主要有两个:

  • 锁住对Inode的访问。
  • 将磁盘上inode信息拷贝到对应的icache中的inode中。

6. iunlock函数

iunlock主要就是释放持有的inode的睡眠锁:

Xv6内核分析(十六)

7. iput函数

iget和iput需要成对使用,iput用于减少对inode的引用计数,如果满足条件的话,还需要删除文件,回收inode资源。

Xv6内核分析(十六)

  • inode中的nlink表示一个文件的链接个数,如果nlink为0表示该文件要被删除,这时就需要回收该Inode的资源。
  • 如果文件需要删除,调用itrunc函数回收资源,itrunc函数在inode内容一小节具体分析。接着将type置0,表示此inode空闲,然后调用iupdate将内存中的inode信息更新到磁盘上,最后将valid置0。
  • 无论iput是否需要回收Inode资源,都需要将inode中的引用计数减一。

8. iupdate函数

iupdate的功能就是将内存中的Inode信息更新到磁盘上的inode中:

Xv6内核分析(十六)

  • 首先读取磁盘Inode信息到Buffer cache中。
  • 然后更新dinode对应部分的inode信息。
  • 调用log_write将buffer cache信息会写到磁盘。

9. iunlockput函数

Xv6内核分析(十六)

很简单,就是将unlock和put操作放在一个函数中。

10.idup函数

Xv6内核分析(十六)

idup功能很简单,就是将inode的引用计数加一。

gewenbin
  • 本文由 发表于 2020年12月20日18:42:09
  • 转载请务必保留本文链接:http://www.databusworld.cn/9523.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: