测试标准输入是否能够查找时出现的问题

测试标准输入是否能够查找时出现的问题

我推翻了 中的陈述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还没开封吗?因为我听说通常stdinstdoutstderr在程序开始运行时打开的。

为什么//2可以,为什么//3不行?我认为它们是一样的。

答案1

//1 ./a.out:

如果您不重定向 stdin (无管道和 no <),则 stdin 将从父进程继承。当您a.out在 shell 中以交互方式运行时,它会继承将键盘输入作为 stdin 获取的终端设备。

终端设备通常不可查找,因为它们代表用户交互,但根据 POSIX 标准,lseek可能会返回成功并且不执行任何操作。在 Linux 上lseek失败并显示ESPIPE.

//2 ./a.out < /etc/passwd:

这里 stdin 被重定向到一个打开的文件。正如/etc/passwd常规文件一样,它是可查找的。

//3 cat < /etc/passwd | ./a.out:

在这里,您启动两个进程(cat./a.out)并用管道连接它们。

cat(没有其他参数)读取它的 stdin ( /etc/passwd) 并将其复制到它的 stdout (连接到 的管道./a.out)。这与 的情况不同//2。从标准输入的角度来看,./a.out无法进行查找,因为它只是连接到另一个进程的管道。

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

在这里你有一个命名管道或类似的特殊文件。本案与此类似//3。您与另一个进程有单向连接。而这些都是不可寻找的。

相关内容