我在查看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
系统调用吗?还是别的东西导致了这个?
答案 0 :(得分:5)
在版本7 UNIX中,只有一个unix文件系统,其目录采用简单的磁盘格式: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库通过缓冲帮助提高性能,就像在调用getchar()
时在常规文件的stdio中一样,并且它一次执行几千字节的read()
而不是一堆单字节read()
秒。
你永远不会在现代Linux系统上使用原始的无缓冲readdir
系统调用,除非你运行很久以前编译过的可执行文件,或者不遗余力地绕过C库。
答案 1 :(得分:1)
实际上Linux不允许read
用于目录。请参阅man page并搜索错误 EISDIR 。你会发现
如果......(/ p>),read()和pread()函数将失败
fildes参数引用目录,并且实现不允许使用read()或pread()读取目录。应该使用readdir()函数。
。其他UNIX允许它。