我在看 K&R 2 中的一个例子(8.6 示例 - 列出目录)。它是 Linux 命令 ls
或 Windows 的 dir
的精简版本。该示例显示了 opendir
、readdir
等函数的实现。我已经尝试并逐字输入代码,但它仍然不起作用。它所做的只是打印一个点(对于当前目录)并退出。
我在代码中(在 readdir
的实现中)发现的一件有趣的事情是它正在调用像 open
和 read
这样的系统调用> 在目录上。像-
int fd, n;
char buf[1000], *bufp;
bufp = buf;
fd = open("dirname", O_RDONLY, 0);
n = read(fd, bufp, 1000);
write(fd, bufp, n);
当我运行这段代码时,即使文件夹名称 "dirname"
中有一些文件,我也没有得到任何输出。
另外,书中还说,该实现是针对Version 7 和 System V UNIX 系统。这就是它不能在 Linux 上运行的原因吗?
这是代码- http://ideone.com/tw8ouX .
那么 Linux 是否不允许对目录进行 read
系统调用?还是其他原因造成的?
最佳答案
在第 7 版 UNIX 中,只有一个 unix 文件系统,其目录有一种简单的磁盘格式:struct direct
数组。阅读它并解释结果是微不足道的。系统调用是多余的。
在现代,Linux 和其他类 unix 系统(ext4、ZFS、NTFS!)可以挂载多种文件系统,其中一些具有复杂的目录格式。您不能对任意目录的原始字节做任何有意义的事情。因此内核承担了为作为抽象对象的目录提供通用接口(interface)的责任。 readdir
是该界面的核心部分。
一些现代的 unices 仍然允许在目录上使用 read()
,因为这是他们历史的一部分。 Linux 的历史始于 90 年代,当时很明显目录上的 read()
永远不会有用,因此 Linux 从未允许这样做。
Linux 确实提供了一个 readdir
系统调用,但它不再被广泛使用,因为出现了更好的东西:getdents
。 readdir 一次只返回一个目录条目,因此如果您在循环中使用 readdir 系统调用来获取目录中的文件列表,则每次循环迭代都会进入内核。 getdents 将多个条目返回到缓冲区中。
readdir
是标准接口(interface),因此 glibc 提供了一个 readdir 函数,它调用 getdents 系统调用而不是 readdir 系统调用。在普通程序中,您会在源代码中看到 readdir,但在 strace 中看到 getdents。 C 库通过缓冲来提高性能,就像它在 stdio 中对常规文件所做的那样,当您调用 getchar()
时它会执行几千字节的 read()
一个时间而不是一堆单字节 read()
s。
你永远不会在现代 Linux 系统上使用原始的无缓冲 readdir
系统调用,除非你运行一个很久以前编译的可执行文件,或者绕过 C 库。
关于c - 在目录上使用 `read` 系统调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17618472/