【问题标题】:K&R interface for reading directories: superfluous DIR structure?读取目录的K&R接口:多余的DIR结构?
【发布时间】:2010-09-17 13:27:10
【问题描述】:

在 Kernighan 和 Ritchie 编写的 “The C Programming Language” 第二版中,他们实现了 UNIX 命令ls 的简化版本(第 8.6 节 “示例 - 列出目录”,第 179 页)。为此,他们创建了以下接口,该接口提供了对存储在目录中的文件的名称和 inode 号的独立于系统的访问。

#define NAME_MAX 14   /* longest filename component; */
                              /* system dependent */

typedef struct {      /* portable director-entry */
    long ino;                 /* inode number */
    char name[NAME_MAX+1];    /* name + '\0' terminator */
} Dirent;

typedef struct {      /* minimal DIR: no buffering, etc. */
    int fd;                   /* file descriptor for directory */
    Dirent d;                 /* the directory entry */
} DIR;

DIR *opendir(char *dirname);
Dirent *readdir(DIR *dfd);
void closedir(DIR *dfd);

然后他们为版本 7 和 System V UNIX 系统实现此接口。

  • opendir()基本用系统 致电open() 打开目录并 malloc() 为 a 分配空间 DIR 结构。文件描述符 然后存储open() 返回的 在那个DIR 的变量fd 中。 Dirent 中没有存储任何内容 组件。

  • readdir() 使用系统调用 read() 获取下一个 (系统相关的)目录条目 打开的目录并复制so 获得inode编号和文件名 进入静态Dirent 结构(到 返回一个指针)。这 唯一需要的信息 readdir() 是文件描述符 存储在DIR 结构中。

现在我的问题:拥有DIR 结构有什么意义?如果我对这个程序的理解是正确的,DIRDirent 组件是从不使用的,那为什么不用文件描述符替换整个结构,直接使用open()close()

谢谢。

Ps:我知道在现代 UNIX 系统上 read() 不能再用于目录(我已经在 Ubuntu 10.04 上试用过这个程序),但我仍然想确保我没有忽略一些重要的东西这个例子。

【问题讨论】:

    标签: c unix


    【解决方案1】:

    来自 K&R:

    遗憾的是,目录的格式和精确内容并不完全相同 系统的版本。所以我们将任务分成两部分来尝试隔离 非便携部分。外层定义了一个名为 Dirent 的结构和三个例程 opendirreaddirclosedir,以提供系统-独立访问目录条目中的名称和 inode 号。

    所以原因是便携性。他们想要定义一个可以在具有不同统计结构或非标准open()close() 的系统上生存的接口。他们继续围绕它构建一堆可重用的工具,甚至不在乎它们是否在类 Unix 系统上。这就是包装器的意义所在。

    也许它没有被使用,因为他们开始通过定义他们的数据结构(在 DIR 中使用 Dirent)但最终没有使用它。像这样将数据结构分组是很好的设计。

    【讨论】:

    • 便携性也是我的第一个猜测,但经过仔细考虑,我不明白DIR 对此有何贡献。它可以传递给readdir() 的唯一相关信息是文件描述符。我仍然没有看到DIR 中使用了Dirent 组件。不管是什么系统,readdir() 的任何实现都可以有一个静态的Dirent,它可以返回一个指针,所以这不应该是可移植性问题。确实dirwalk() 访问了Dirent 的内容,但这是来自readdir() 的静态内容,而不是DIR 中包含的内容。我错过了什么吗?
    • 嘿,看来你是对的。我的猜测是,他们从定义数据结构开始(在DIR 中使用Dirent),但最终没有使用它。在结构中将相关数据分组在一起是很好的juju。一个好的练习是重写代码以使用DIR.d,而不是让readdir() 的调用者拥有自己的Dirent 指针。
    • 是的,这是一个合理的解释。但是考虑到这本书是20多年前出版的(第2版),奇怪的是errata中没有提到这样的东西。
    • 奇怪,是的。但并非闻所未闻。您链接的勘误表最后一次更新是在 2006 年 10 月,这意味着他们在发布 18 年后发现了一个错误。另外,它实际上并不是损坏的代码。只是浪费了一些内存。
    • 没错,代码没有破解,但是对于我这种初学者来说还是比较混乱的。
    【解决方案2】:

    这样他们就不必为 readdir 返回的 Dirent 结构分配内存。这样他们就可以在对 readdir 的后续调用之间重用 Dirent。

    【讨论】:

    • 但他们不必分配内存,因为readdir()Dirent 存储为静态变量。
    • @qfab:是的,但这是一个非常糟糕的设计。一个假设的改进实现会将缓冲区放在 DIR 结构中,以便同时读取多个目录不会破坏数据(因此只要您不使用单个 DIR 对象,它将是线程安全的一次不止一个线程)。我希望现代实现可以做到这一点;我的当然可以。
    猜你喜欢
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 2017-08-23
    • 2015-11-30
    • 1970-01-01
    • 1970-01-01
    • 2013-04-13
    • 2010-11-27
    相关资源
    最近更新 更多