【发布时间】:2013-05-10 12:38:34
【问题描述】:
我正在尝试将信息传递到不接受来自标准输入的输入的程序中。为此,我使用 /dev/stdin 作为参数,然后尝试输入我的输入。我注意到如果我使用管道字符执行此操作:
[pkerp@comp ernwin]$ cat fess/structures/168d.pdb | MC-Annotate /dev/stdin
我没有输出。但是,如果我使用左脱字符号做同样的事情,它工作正常:
[pkerp@plastilin ernwin]$ MC-Annotate /dev/stdin < fess/structures/168d.pdb
Residue conformations -------------------------------------------
A1 : G C3p_endo anti
A2 : C C3p_endo anti
A3 : G C3p_endo anti
我的问题是,这两个操作有什么区别,为什么它们会给出不同的结果?作为一个额外的问题,是否有使用“
更新:
我目前最好的猜测是正在运行的程序内部的某些东西利用了文件内的查找。下面的答案似乎表明它与文件指针有关,但运行以下小测试程序:
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *f = fopen(argv[1], "r");
char line[128];
printf("argv[1]: %s f: %d\n", argv[1], fileno(f));
while (fgets(line, sizeof(line), f)) {
printf("line: %s\n", line);
}
printf("rewinding\n");
fseek(f, 0, SEEK_SET);
while (fgets(line, sizeof(line), f)) {
printf("line: %s\n", line);
}
fclose(f);
}
表示在fseek 函数调用之前,一切都以相同的方式发生:
[pete@kat tmp]$ cat temp | ./a.out /dev/stdin
argv[1]: /dev/stdin f: 3
line: abcd
rewinding
===================
[pete@kat tmp]$ ./a.out /dev/stdin < temp
argv[1]: /dev/stdin f: 3
line: abcd
rewinding
line: abcd
使用 Christopher Neylan 建议的进程替换会导致上面的程序挂起,甚至没有读取输入,这似乎也有点奇怪。
[pete@kat tmp]$ ./a.out /dev/stdin <( cat temp )
argv[1]: /dev/stdin f: 3
查看 strace 输出证实我怀疑尝试了在管道版本中失败的查找操作:
_llseek(3, 0, 0xffffffffffd7c7c0, SEEK_CUR) = -1 ESPIPE (Illegal seek)
并在重定向版本中成功。
_llseek(3, 0, [0], SEEK_CUR) = 0
故事的寓意:不要随意尝试用/dev/stdin 替换参数并尝试使用它。它可能有效,但也可能无效。
【问题讨论】:
-
这很有趣,但它似乎没有进行这样的检查。无论如何, isatty() 的输出在此处提到的两种输入情况下不应该相同吗?这与没有重定向输入的链接帖子形成对比。
-
根据第二个答案 | isatty 返回 YES 而 stackoverflow.com/a/7601564/2269047