在
./binary < file
binary
的stdin是以只读模式打开的文件。请注意,bash
它根本不读取文件,它只是打开文件以读取其执行过程的文件描述符0(stdin)binary
。
在:
./binary << EOF
test
EOF
根据外壳的不同,binary
stdin可能是一个已删除的临时文件(AT&T ksh,zsh,bash ...),其中包含test\n
该外壳放置在其中的内容,也可能是管道的读取端(dash
,yash
;并且外壳test\n
并行写入)在管道的另一端)。就您而言,如果使用bash
,它将是一个临时文件。
在:
cat file | ./binary
根据外壳的不同,binary
's stdin将是管道的读取端,或者是套接字对的一端,其中写入方向已关闭(ksh93),并且cat
正在file
另一端写入内容。
当stdin是常规文件(临时文件)时,它是可搜索的。binary
可能会开始或结束,倒带等。它也可以ioctl()s
映射它,做一些像FIEMAP / FIBMAP的操作(如果使用<>
代替<
,可能会在其中截断/打孔等等)。
另一方面,管道和套接字对是一种进程间的通信方式,binary
除了read
数据之外没有什么可以做的(尽管也有一些操作,例如某些特定ioctl()
于管道的操作,可以对它们而不是对常规文件执行) 。
大多数时候,它是在缺少能力seek
与管工作时,导致应用程序故障/投诉,但它可以是任何其他系统调用是在常规文件上有效,但不能在不同类型的文件(如mmap()
,ftruncate()
,fallocate()
) 。在Linux上,当/dev/stdin
fd 0在管道或常规文件上打开时,行为上也存在很大差异。
有很多命令只能处理可搜索的文件,但是在这种情况下,通常不是针对在其stdin上打开的文件。
$ unzip -l file.zip
Archive: file.zip
Length Date Time Name
--------- ---------- ----- ----
11 2016-12-21 14:43 file
--------- -------
11 1 file
$ unzip -l <(cat file.zip)
# more or less the same as cat file.zip | unzip -l /dev/stdin
Archive: /proc/self/fd/11
End-of-central-directory signature not found. Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive. In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
unzip: cannot find zipfile directory in one of /proc/self/fd/11 or
/proc/self/fd/11.zip, and cannot find /proc/self/fd/11.ZIP, period.
unzip
需要读取存储在文件末尾的索引,然后在文件内搜索以读取存档成员。但是在这里,文件(在第一种情况下为常规,在第二种情况下为管道)作为路径参数提供给unzip
,并unzip
自行打开文件(通常在非0的fd上),而不继承父级已经打开的fd。它不会从其stdin中读取zip文件。stdin主要用于用户交互。
如果您binary
在终端仿真器中运行的交互式shell的提示下运行了自己的代码而没有重定向,则binary
stdin将从其父级shell继承而来,它本身将从其父级终端仿真器继承而来,它将是一个pty设备以读写模式打开(类似/dev/pts/n
)。
这些设备也不是可搜索的。因此,如果binary
从终端获取输入时可以正常工作,则可能问题不在于寻找。
如果该14表示errno(系统调用失败而设置的错误代码),则在大多数系统上,该值为EFAULT
(Bad address)。在read()
如果要求读成不可写一个内存地址系统调用会失败与错误。这将与fd从点读取数据到管道还是常规文件无关,并且通常会指示bug 1。
binary
可能确定在其stdin(带有fstat()
)上打开的文件的类型,并且在既不是常规文件又不是tty设备的情况下都会遇到错误。
在不了解应用程序的情况下很难说出来。下运行它strace
(或truss
/ tusc
您的系统上等效)可以帮助我们来看看什么是系统调用,如果任何失败在这里。
1 马修·伊夫(Matthew Ife)在对您的问题的评论中提出的设想在这里听起来很合理。引用他:
我怀疑它正在寻求到文件末尾以获取用于读取数据的缓冲区大小,从而严重处理了查找不起作用的事实,并试图分配负大小(不处理错误的malloc)。传递缓冲区以读取给定缓冲区的哪些故障无效。