我在写一个C程序,就像,

void printdir (char*);

int main () {
    printf ("Directory scan of /home: \n");
    printdir ("/home/fahad/");
    exit (0);
}

void printdir (char *dir) {
    struct dirent *entry;
    DIR *dp = opendir (dir);

    if (dp == NULL) {
        fprintf (stderr, "Cannot open dir:%s\n", dir);
        return;
    }

    chdir (dir);
    while ((entry = readdir(dp)) != NULL)
        printf ("%s\n",entry -> d_name);
    closedir (dp);
}

有趣的是,它以一种意想不到的方式显示输出。
考虑到无论何时在UNIX中创建目录。前两个条目是在这个目录中创建的,一个是.,另一个是..。因此基本上,它们的inode编号应该小于通过mkdir ()open ()创建的目录条目(分别用于目录和文件)。
我的问题是,系统调用按什么顺序读取目录条目?因为我没有第一个输入readdir ().的人。
为什么会这样?

最佳答案

readdir()不按任何特定顺序返回条目。正如其他人提到的,顺序将取决于所讨论的特定文件系统。
例如,Berkeley UFS文件系统使用未排序的链表。参见http://ptgmedia.pearsoncmg.com/images/0131482092/samplechapter/mcdougall_ch15.pdf第744页上的direct结构说明。目录的二进制内容由可变长度的记录流组成,每个记录流包含索引节点号、记录长度、字符串长度(文件名)和字符串数据本身。readdir()通过遍历链接列表(使用记录长度来知道每个记录相对于上一个记录的开始位置)并返回找到的任何内容来工作。
记录列表通常没有优化,因此文件名按创建文件的顺序显示在列表中(或多或少)。但不完全是这样,因为洞(由删除的文件造成)将填充新的文件名,如果它们足够小,以适应。
现在,并不是所有的文件系统都像UFS那样表示目录。将目录数据保存在二叉树中的文件系统可以选择将readdir()实现为该树的按顺序遍历,该树将显示按其用作该树键的任何属性排序的文件。或者它可能使用预先排序的遍历,这样就不会按排序的顺序返回记录。
由于应用程序无法知道文件系统实现的性质(并且每个装入的卷都可能使用不同的文件系统),因此应用程序不应假定readdir()返回项的顺序。如果需要对条目进行排序,则必须将整个目录读入内存并进行自己的排序。
例如,这就是为什么在对大目录运行时,ls命令可能需要很长时间才能显示输出。它需要对整个名称列表进行排序(并确定最长的名称,以便计算列宽),然后才能显示任何输出。这也是为什么ls -1U(禁用一列中的排序和显示)将立即在此类目录上生成输出。

10-07 19:38
查看更多