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

Shu*_*hya 3 c directory operating-system system-calls kernighan-and-ritchie

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

我在代码中找到的一个有趣的事情(在实现中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);
Run Code Online (Sandbox Code Playgroud)

当我运行此代码时,即使文件夹名称中"dirname"包含一些文件,我也没有输出.

此外,该书还说,该实现适用于版本7和System V UNIX系统.这就是它不能在Linux上工作的原因吗?

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

那么Linux不允许read对目录进行系统调用吗?还是别的东西导致了这个?

小智 5

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

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

一些现代统一仍然允许read()在目录上,因为它是他们历史的一部分.Linux的历史始于90年代,当时很明显read()在一个目录上永远不会有用,所以Linux从未允许它.

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

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

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


Ing*_*rdt 3

事实上Linux 不允许read目录。请参阅手册页并搜索 errno EISDIR。你会找到

read() 和 pread() 函数将失败,如果......

fildes 参数引用一个目录,并且实现不允许使用 read() 或 pread() 读取该目录。应改用 readdir() 函数。

。尽管如此,其他 UNIX 仍然允许这样做。