disk一层,没有涉及到
buffer cache 和 logging 已经分别写了博客
所以本文从inode讲起:
inode
首先看文件系统的结构:
inode有两层含义:磁盘上的inode和内存中的inode,磁盘中的inode数据结构如下:一系列dinode就保存在上图中inodes区里
dinode的大小都相同,因此给出数字n(实际上就是inum),很容易定位到第n个inode
// On-disk inode structure
struct dinode {
short type; // File type
short major; // Major device number (T_DEVICE only)
short minor; // Minor device number (T_DEVICE only)
short nlink; // Number of links to inode in file system
uint size; // Size of file (bytes)
uint addrs[NDIRECT+1]; // Data block addresses
};
前面几个属性的意图,在注释里都有很好的说明。nlink的link,可以理解为有多少个硬链接(包括文件本身)指向该inode
至于addrs,则是保存了inode内容的数据块的地址
内核将活跃或者说有指针指向它的inode保存在内存里,他相对磁盘上的inode,增加了一些额外属性:
// in-memory copy of an inode
struct inode {
uint dev; // Device number
uint inum; // Inode number
int ref; // Reference count
struct sleeplock lock; // protects everything below here
int valid; // inode has been read from disk?
short type; // copy of disk inode
short major;
short minor;
short nlink;
uint size;
uint addrs[NDIRECT+1];
};
dev和inum指明当前inode对应磁盘上哪一个inode(dinode)
ref表明有多少个指针指向本inode
因为对inode的操作可能用时较长,所以这里用的睡眠锁
valid则指示当前inode是否包含对应dinode的数据(即dinode的成员变量)
在inode的代码中,有四个锁/类似锁(主要指计数)的机制,来保护下面的invariant:
- icache.lock:保证 1.磁盘上的一个inode最多对应缓存中的一个inode,2. 内存中inode的ref字段记录指向这个inode的指针数
- inode.lock保证了对inode的独占访问
- 如果inode的ref大于0,就不会被evict,或者说从cache里被回收利用
- inode的nlink如果大于0,就不会被释放
update:2020年11月9日
fs.c中inode部分代码的开头注释有一段是对icache.lock和ip->lock的描述,之前没有注意到:
从ip->ref(指示对这个inode的ref的数量,包括open files和cwd)能判断一个inode buf应不应该在icache里
ip-dev,ip->num表明icache entry缓存的是哪一个inode
综上两点,当使用上述三个field时,需要持有icache.lock
而ip->lock则保护除上述三个属性之外的field
// Find the inode with number inum on device dev
// and return the in-memory copy. Does not lock
// the inode and does not read it from disk.
static struct inode*
iget(uint dev, uint inum)
{
struct inode *ip, *empty;
acquire(&icache.lock);
// Is the inode already cached?
empty = 0;
for(ip = &icache.inode[0]; ip < &icache.inode[NINODE]; ip++){
if(ip->ref > 0 && ip->dev == dev && ip->inum == inum){
ip->ref++;
release(&icache.lock);
return ip;
}
if(empty == 0 && i