Api

測試標準輸入是否能夠搜尋時的問題

  • May 12, 2019

我顛倒了 中的陳述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

為什麼//1cannot seek?空stdin應該可以求我想。是因為stdin還沒開嗎?因為我聽說正常stdinstdout並且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.outstdin 的角度來看,它是無法查找的,因為它只是連接到另一個程序的管道。

//4 ./a.out < /var/spool/cron/FIFO:

在這裡,您有一個命名管道或類似的特殊文件。這種情況類似於//3。您與另一個程序建立了單向連接。這些是不可搜尋的。

引用自:https://unix.stackexchange.com/questions/502518