不知道你是否还记得文件系统相关的知识,不然下面的内容可能会让你感不到适_.
1. 回忆
先简单梳理下几个概念:
- 文件表、文件表项
- 文件描述符与文件表
- inode 节点
这些内容之前都有讲过,请参考 文件IO-文件描述符与lseek,inode 节点实际上就是一个结构体对象。
实际上,文件系统的实现中并没有直接采用 inode 节点,而是又抽象出了一个 vnode 节点,它是对 inode 节点的再一次封装,这是为了屏蔽不同文件系统之间的差异性。关于这一点,大家知道就好。
2. 记录锁实现
假设有下面一段程序:
// 下面的程序中,假设 fd1 = 3, fd2 = 4, fd3 = 5
fd1 = open(pathname, ...);
// 对第一个字节加写锁
wlock(fd1, 0, SEEK_SET, 1);
pid = fork();
if (pid > 0) {
// 父进程,假设 pid = 1000
fd2 = dup(fd1);
fd3 = open(pathname, ...);
}
else if (pid == 0) {
// 子进程,假设 pid = 1001
// 对第二个字节加读锁。
rlock(fd1, 1, SEEK_SET, 1);
}
这段程序执行完后,内核中的数据结构情况如图 1.
从图 1 中可以看到:
- 对于同一个文件,只有一份 vnode,无论是 dup 还是 open
- 锁的信息是保存在 vnode 中的
上面的实现告诉我们,对任何一个文件描述符进行加锁和解锁的操作,都会影响到所有最终指向 vnode 节点的描述符。
比如说如果在 fd1 上释放了锁,那么对于 fd2 和 fd3 来说,锁也是释放了的。
看值一提的是,关闭任何一个描述符,锁都会释放。
3. 总结
- 掌握图 1 中的结构关系
- 知道记录锁保存在哪个位置