c - 在目录上使用 `read` 系统调用

标签 c operating-system directory system-calls kernighan-and-ritchie

我在看 K&R 2 中的一个例子(8.6 示例 - 列出目录)。它是 Linux 命令 ls 或 Windows 的 dir 的精简版本。该示例显示了 opendirreaddir 等函数的实现。我已经尝试并逐字输入代码,但它仍然不起作用。它所做的只是打印一个点(对于当前目录)并退出。

我在代码中(在 readdir 的实现中)发现的一件有趣的事情是它正在调用像 openread 这样的系统调用> 在目录上。像-

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/

相关文章:

c - 我如何访问 C 中的隐藏变量

c - C 中的 free() 数据 block

c# - 删除所有没有特定扩展名文件的文件夹和子目录

file - Centos:合并目录,同时删除所有子目录中的公共(public)子目录

c - 将 uint8_t 而不是 uint32_t 传递给函数(在 C 中)

c - 创建另一个线程后Main()线程id不同

linux - 操作系统如何知道缺失页面的磁盘地址?

python - 如何在 Python 中获取 PATH 环境变量分隔符?

c - 如何找到正在运行的进程的平台

java - 如何读取 Maven Web 应用程序的 webapp 文件夹中的目录