# 8.11 代码：目录层

目录的内部实现很像文件。其inode的`type`为`T_DIR`，其数据是一系列目录条目（directory entries）。每个条目（entry）都是一个`struct dirent`（***kernel/fs.h***:56），其中包含一个名称`name`和一个inode编号`inum`。名称最多为`DIRSIZ`（14）个字符；如果较短，则以`NUL`（0）字节终止。inode编号为零的条目是空的。

函数`dirlookup`（***kernel/fs.c***:527）在目录中搜索具有给定名称的条目。如果找到一个，它将返回一个指向相应inode的指针，解开锁定，并将`*poff`设置为目录中条目的字节偏移量，以满足调用方希望对其进行编辑的情形。如果`dirlookup`找到具有正确名称的条目，它将更新`*poff`并返回通过`iget`获得的未锁定的inode。`Dirlookup`是`iget`返回未锁定indoe的原因。调用者已锁定`dp`，因此，如果对`.`，当前目录的别名，进行查找，则在返回之前尝试锁定indoe将导致重新锁定`dp`并产生死锁(还有更复杂的死锁场景，涉及多个进程和`..`，父目录的别名。`.`不是唯一的问题。）调用者可以解锁`dp`，然后锁定`ip`，确保它一次只持有一个锁。

函数`dirlink`（***kernel/fs.c***:554）将给定名称和inode编号的新目录条目写入目录`dp`。如果名称已经存在，`dirlink`将返回一个错误（***kernel/fs.c***:560-564）。主循环读取目录条目，查找未分配的条目。当找到一个时，它会提前停止循环（***kernel/fs.c***:538-539），并将`off`设置为可用条目的偏移量。否则，循环结束时会将`off`设置为`dp->size`。无论哪种方式，`dirlink`都会通过在偏移`off`处写入（***kernel/fs.c***:574-577）来向目录添加一个新条目。