在目录上使用 `read` 系统调用 [英] Using `read` system call on a directory

查看:20
本文介绍了在目录上使用 `read` 系统调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I was looking at an example in K&R 2 (8.6 Example - Listing Directories). It is a stripped down version of Linux command ls or Windows' dir. The example shows an implementation of functions like opendir, readdir. I've tried and typed the code word-by-word but it still doesn't work. All it does is that it prints the a dot (for the current directory) and exits.

我在代码中发现了一件有趣的事情(在 readdir 的实现中),它正在调用像 openread 在目录上.有点像 -

One interesting thing I found in the code (in the implementation of readdir) was that it was calling the system calls like open and read on directory. Something like -

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" 中有一些文件,我也没有得到任何输出.

When I run this code I get no output even when the folder name "dirname" has some files in it.

另外,这本书说,该实现适用于版本 7 和 System V UNIX 系统.这就是它无法在 Linux 上运行的原因吗?

Also, the book says, that the implementation is for Version 7 and System V UNIX systems. Is that the reason why it is not working on Linux?

这里是代码 - http://ideone.com/tw8ouX.

那么 Linux 不允许对目录进行 read 系统调用吗?还是其他原因造成的?

So does Linux not allow read system calls on directories? Or something else is causing this?

推荐答案

在版本 7 UNIX 中,只有一个 unix 文件系统,它的目录有一个简单的磁盘格式:array of struct direct.阅读它并解释结果是微不足道的.系统调用将是多余的.

In Version 7 UNIX, there was only one unix filesystem, and its directories had a simple on-disk format: array of struct direct. Reading it and interpreting the result was trivial. A syscall would have been redundant.

在现代,有多种文件系统可以被 Linux 和其他类 unix 系统(ext4、ZFS、NTFS!)挂载,其中一些具有复杂的目录格式.你不能对任意目录的原始字节做任何明智的事情.因此内核承担了为目录提供通用接口作为抽象对象的责任.readdir 是该界面的核心部分.

In modern times there are many kinds of filesystems that can be mounted by Linux and other unix-like systems (ext4, ZFS, NTFS!), some of which have complex directory formats. You can't do anything sensible with the raw bytes of an arbitrary directory. So the kernel has taken on the responsibility of providing a generic interface to directories as abstract objects. readdir is the central piece of that interface.

一些现代 unice 仍然允许 read() 在目录上,因为它是它们历史的一部分.Linux 的历史始于 90 年代,当时已经很明显,目录上的 read() 永远不会有用,因此 Linux 从未允许这样做.

Some modern unices still allow read() on a directory, because it's part of their history. Linux history began in the 90's, when it was already obvious that read() on a directory was never going to be useful, so Linux has never allowed it.

Linux 确实提供了一个 readdir 系统调用,但它不再被大量使用,因为出现了更好的东西:getdents.readdir 一次只返回一个目录条目,因此如果您在循环中使用 readdir 系统调用来获取目录中的文件列表,您将在每次循环迭代时进入内核.getdents 将多个条目返回到缓冲区中.

Linux does provide a readdir syscall, but it's not used very much anymore, because something better has come along: getdents. readdir only returns one directory entry at a time, so if you use the readdir syscall in a loop to get a list of files in a directory, you enter the kernel on every loop iteration. getdents returns multiple entries into a buffer.

readdir 是标准接口,因此 glibc 提供了一个 readdir 函数,该函数调用 getdents 系统调用而不是 readdir 系统调用.在普通程序中,您会在源代码中看到 readdir,但在 strace 中看到 getdents.C 库通过缓冲来提高性能,就像它在 stdio 中对常规文件所做的那样,当您调用 getchar() 时,它会执行几千字节的 read()一次而不是一堆单字节 read()s.

readdir is, however, the standard interface, so glibc provides a readdir function that calls the getdents syscall instead of the readdir syscall. In an ordinary program you'll see readdir in the source code, but getdents in the strace. The C library is helping performance by buffering, just like it does in stdio for regular files when you call getchar() and it does a read() of a few kilobytes at a time instead of a bunch of single-byte read()s.

你永远不会在现代 Linux 系统上使用原始的无缓冲 readdir 系统调用,除非你运行很久以前编译的可执行文件,或者想方设法绕过 C 库.

You'll never use the original unbuffered readdir syscall on a modern Linux system unless you run an executable that was compiled a long time ago, or go out of your way to bypass the C library.

这篇关于在目录上使用 `read` 系统调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆