Appearance
代码:系统调用
有了底层提供的函数,大多数系统调用的实现都是微不足道的(见 kernel/sysfile.c
)。有几个调用值得仔细研究。
函数 sys_link
和 sys_unlink
编辑目录,创建或删除对 inode 的引用。它们是使用事务强大功能的另一个好例子。sys_link
首先获取其参数,两个字符串 old
和 new
。假设 old
存在且不是目录,sys_link
增加其 ip->nlink
计数。然后 sys_link
调用 nameiparent
来查找 new
的父目录和最后一个路径元素并创建一个指向 old
的 inode 的新目录条目。新的父目录必须存在并且与现有 inode 在同一设备上:inode 号仅在单个磁盘上有唯一含义。如果发生此类错误,sys_link
必须返回并减少 ip->nlink
。
事务简化了实现,因为它需要更新多个磁盘块,但我们不必担心我们执行它们的顺序。它们要么全部成功,要么全部失败。例如,没有事务,在创建链接之前更新 ip->nlink
,会使文件系统暂时处于不安全状态,而中间的崩溃可能会导致混乱。有了事务,我们就不必担心这个问题了。
sys_link
为现有 inode 创建一个新名称。函数 create
为新 inode 创建一个新名称。它是三个文件创建系统调用的泛化:带有 O_CREATE
标志的 open
创建一个新的普通文件,mkdir
创建一个新目录,而 mkdev
创建一个新的设备文件。像 sys_link
一样,create
首先调用 nameiparent
来获取父目录的 inode。然后它调用 dirlookup
来检查名称是否已存在。如果名称确实存在,create
的行为取决于它被用于哪个系统调用:open
的语义与 mkdir
和 mkdev
不同。如果 create
代表 open
被使用(type == T_FILE
)并且存在的名称本身是一个常规文件,那么 open
将其视为成功,所以 create
也这样做。否则,这是一个错误。如果名称尚不存在,create
现在用 ialloc
分配一个新的 inode。如果新的 inode 是一个目录,create
用 .
和 ..
条目初始化它。最后,既然数据已正确初始化,create
可以将其链接到父目录中。create
,像 sys_link
一样,同时持有两个 inode 锁:ip
和 dp
。不存在死锁的可能性,因为 inode ip
是新分配的:系统中的没有其他进程会持有 ip
的锁,然后尝试锁定 dp
。
使用 create
,很容易实现 sys_open
、sys_mkdir
和 sys_mknod
。sys_open
是最复杂的,因为创建一个新文件只是它能做的一小部分。如果 open
被传递 O_CREATE
标志,它会调用 create
。否则,它会调用 namei
。create
返回一个锁定的 inode,但 namei
不返回,所以 sys_open
必须自己锁定 inode。这提供了一个方便的地方来检查目录是否只为读取而打开,而不是写入。假设 inode 以某种方式获得,sys_open
分配一个文件和一个文件描述符然后填充该文件。请注意,没有其他进程可以访问部分初始化的文件,因为它只在当前进程的表中。
第 4 章在我们甚至还没有文件系统之前就研究了管道的实现。函数 sys_pipe
通过提供一种创建管道对的方法,将该实现与文件系统连接起来。它的参数是一个指向两个整数空间的指针,它将在那里记录两个新的文件描述符。然后它分配管道并安装文件描述符。