优秀的编程知识分享平台

网站首页 > 技术文章 正文

理解xv6——6.8 索引结点层(索引结构)

nanyue 2024-09-05 18:13:13 技术文章 4 ℃

The term inode can have one of two related meanings. It might refer to the on-disk data structure containing a file’s size and list of data block numbers. Or ‘‘inode’’ might refer to an in-memory inode, which contains a copy of the on-disk inode as well as extra information needed within the kernel.

inode 这个术语有两种相关的含义。它可能指的是包含文件大小和数据块编号列表的磁盘上的数据结构。或者,“inode”可能指的是内存中的 inode,它包含磁盘上 inode 的副本以及内核中所需的额外信息。


The on-disk inodes are packed into a contiguous area of disk called the inode blocks. Every inode is the same size, so it is easy, given a number n, to find the nth inode on the disk. In fact, this number n, called the inode number or i-number, is how inodes are identified in the implementation.

磁盘上的inode被打包到称为inode块的连续磁盘区域中。每个inode都是相同的大小,所以很容易找到磁盘上的第n个inode。实际上,这个数字n,称为inode编号或i-number,是在实现中标识inode的方式。


The on-disk inode is defined by a struct dinode (4078) . The type field distinguishes between files, directories, and special files (devices). A type of zero indicates that an on-disk inode is free. The nlink field counts the number of directory entries that refer to this inode, in order to recognize when the on-disk inode and its data blocks should be freed. The size field records the number of bytes of content in the file. The addrs array records the block numbers of the disk blocks holding the file’s content.

磁盘上的 inode 由结构体 dinode (4078) 定义。类型字段区分文件、目录和特殊文件(设备)。类型为零表示磁盘上的 inode 是空闲的。nlink 字段计算引用此 inode 的目录项数量,以便识别何时释放磁盘上的 inode 及其数据块。size 字段记录文件内容的字节数。addrs 数组记录了保存文件内容的磁盘块的块号。


The kernel keeps the set of active inodes in memory; struct inode (4162) is the in-memory copy of a struct dinode on disk. The kernel stores an inode in memory only if there are C pointers referring to that inode. The ref field counts the number of C pointers referring to the in-memory inode, and the kernel discards the inode from memory if the reference count drops to zero. The iget and iput functions acquire and release pointers to an inode, modifying the reference count. Pointers to an inode can come from file descriptors, current working directories, and transient kernel code such as exec.

内核将活动 inode 的集合保存在内存中;struct inode (4162) 是磁盘上 struct dinode 的内存副本。只有当有 C 指针引用该 inode 时,内核才会将 inode 存储在内存中。ref 字段计算引用内存中 inode 的 C 指针数量,如果引用计数降至零,内核将从内存中丢弃该 inode。iget 和 iput 函数获取和释放对 inode 的指针,修改引用计数。指向 inode 的指针可以来自文件描述符、当前工作目录和诸如 exec 等临时内核代码。


There are four lock or lock-like mechanisms in xv6’s inode code. icache.lock protects the invariant that an inode is present in the cache at most once, and the invariant that a cached inode’s ref field counts the number of in-memory pointers to the cached inode. Each in-memory inode has a lock field containing a sleep-lock, which ensures exclusive access to the inode’s fields (such as file length) as well as to the inode’s file or directory content blocks. An inode’s ref, if it is greater than zero, causes the system to maintain the inode in the cache, and not re-use the cache entry for a different inode. Finally, each inode contains a nlink field (on disk and copied in memory if it is cached) that counts the number of directory entries that refer to a file; xv6 won’t free an inode if its link count is greater than zero.

xv6 的 inode 代码中有四种锁或类似锁的机制。icache.lock 保护了一个不变量,即 inode 在缓存中最多出现一次,以及一个缓存的 inode 的 ref 字段计算指向缓存的 inode 的内存指针数量的不变量。每个内存中的 inode 都有一个包含睡眠锁的锁字段,这确保了对 inode 的字段(如文件长度)以及 inode 的文件或目录内容块的独占访问。如果 inode 的 ref 大于零,则系统将保持该 inode 在缓存中,并不会将缓存条目重新用于不同的 inode。最后,每个 inode 都包含一个 nlink 字段(在磁盘上并在内存中复制,如果它被缓存),该字段计算引用文件的目录项的数量;如果 inode 的链接计数大于零,xv6 不会释放该 inode。


A struct inode pointer returned by iget() is guaranteed to be valid until the corresponding call to iput(); the inode won’t be deleted, and the memory referred to by the pointer won’t be re-used for a different inode. iget() provides non-exclusive access to an inode, so that there can be many pointers to the same inode. Many parts of the file system code depend on this behavior of iget(), both to hold long-term references to inodes (as open files and current directories) and to prevent races while avoiding deadlock in code that manipulates multiple inodes (such as pathname lookup).

由 iget() 返回的 struct inode 指针保证在相应的 iput() 调用之前有效;inode 不会被删除,并且指针所引用的内存不会被重新用于不同的 inode。iget() 提供了对 inode 的非独占访问,因此可以有多个指向相同 inode 的指针。文件系统代码的许多部分都依赖于 iget() 的这种行为,既要持有对 inode 的长期引用(如打开的文件和当前目录),又要在处理多个 inode 的代码中(如路径名查找)避免竞态条件和死锁。


The struct inode that iget returns may not have any useful content. In order to ensure it holds a copy of the on-disk inode, code must call ilock. This locks the inode (so that no other process can ilock it) and reads the inode from the disk, if it has not already been read. iunlock releases the lock on the inode. Separating acquisition of inode pointers from locking helps avoid deadlock in some situations, for example during directory lookup. Multiple processes can hold a C pointer to an inode returned by iget, but only one process can lock the inode at a time.

iget 返回的 struct inode 可能没有任何有用的内容。为了确保它持有磁盘上 inode 的副本,代码必须调用 ilock。这会锁定 inode(以便其他进程无法锁定它),并从磁盘读取 inode,如果它尚未被读取。iunlock 释放对 inode 的锁定。将获取 inode 指针与锁定分开有助于在某些情况下避免死锁,例如在目录查找期间。多个进程可以持有指向 iget 返回的 inode 的 C 指针,但一次只能有一个进程锁定 inode。


The inode cache only caches inodes to which kernel code or data structures hold C pointers. Its main job is really synchronizing access by multiple processes; caching is secondary. If an inode is used frequently, the buffer cache will probably keep it in memory if it isn’t kept by the inode cache. The inode cache is write-through, which means that code that modifies a cached inode must immediately write it to disk with iupdate.

inode 缓存仅缓存内核代码或数据结构持有 C 指针的 inode。它的主要工作实际上是同步多个进程的访问;缓存是次要的。如果一个 inode 被频繁使用,那么如果缓冲缓存没有保留它,它可能会将其保留在内存中。inode 缓存是写透的,这意味着修改缓存的 inode 的代码必须立即使用 iupdate 将其写入磁盘。

Tags:

最近发表
标签列表