測試標準輸入是否能夠搜尋時的問題
我顛倒了 中的陳述
if/else
,現在更正了。我正在閱讀來自UNIX® 環境中的高級程式的程式碼片段:
該程序測試其標準輸入以查看它是否能夠搜尋。
#include <sys/types.h> #include <unistd.h> #include <stdio.h> int main(void){ if(lseek(STDIN_FILENO,0, SEEK_CUR) == -1) printf("cannot seek\n"); else{ printf("seek ok\n"); } }
我編譯並執行它(在 下
Ubuntu 18.04.2 LTS
)但不理解以下行為。//1 $ ./a.out cannot seek //2 $ ./a.out < /etc/passwd seek OK //3 $ cat < /etc/passwd | ./a.out cannot seek //4 $ ./a.out < /var/spool/cron/FIFO cannot seek
為什麼
//1
是cannot seek
?空stdin
應該可以求我想。是因為stdin
還沒開嗎?因為我聽說正常stdin
,stdout
並且stderr
在程序開始執行時打開。為什麼
//2
可以,//3
不可以?我認為他們是一樣的。
//1 ./a.out
:如果你不重定向標準輸入(沒有管道和沒有
<
),標準輸入是從父程序繼承的。當您a.out
在 shell 中以互動方式執行時,它會繼承將您的鍵盤輸入作為標準輸入的終端設備。終端設備通常不可搜尋,因為它們代表使用者互動,但根據 POSIX 標準,
lseek
可能會返回成功並且什麼也不做。在 Linux 上lseek
失敗並顯示ESPIPE
.
//2 ./a.out < /etc/passwd
:這裡標準輸入被重定向到一個打開的文件。
/etc/passwd
應該是一個正常文件,它是可搜尋的。
//3 cat < /etc/passwd | ./a.out
:在這裡,您啟動兩個程序 (
cat
和./a.out
) 並用管道連接它們。
cat
(沒有其他參數)讀取它 stdin (/etc/passwd
) 並將其複製到它的 stdout (連接到 的管道./a.out
)。這與//2
. 從./a.out
stdin 的角度來看,它是無法查找的,因為它只是連接到另一個程序的管道。
//4 ./a.out < /var/spool/cron/FIFO
:在這裡,您有一個命名管道或類似的特殊文件。這種情況類似於
//3
。您與另一個程序建立了單向連接。這些是不可搜尋的。