簡體   English   中英

在目錄上使用`read`系統調用

[英]Using `read` system call on a directory

我在K&R 2 (8.6示例 - 列表目錄)中查看示例。 它是Linux命令ls或Windows' dir的精簡版本。 該示例顯示了opendirreaddir等函數的實現。 我已經嘗試過逐字輸入代碼,但它仍然不起作用。 它所做的只是打印一個點(對於當前目錄)並退出。

我在代碼中找到的一個有趣的事情(在readdir的實現中)是它調用系統調用如openread on directory。 就像是 -

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"包含一些文件,我也沒有輸出。

此外,該書還說,該實現適用於版本7和System V UNIX系統 這就是它不能在Linux上工作的原因嗎?

這是代碼 - http://ideone.com/tw8ouX

那么Linux不允許對目錄進行read系統調用嗎? 還是別的東西導致了這個?

在V7 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庫。

實際上Linux不允許read目錄。 請參見手冊頁並搜索errno EISDIR 你會找到

如果......,read()和pread()函數將失敗

fildes參數引用目錄,並且實現不允許使用read()或pread()讀取目錄。 應該使用readdir()函數。

其他UNIX允許它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM