我颠倒了 中的陈述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
。您与另一个进程建立了单向连接。这些是不可搜索的。