に
./binary < file
binary
の標準入力は、読み取り専用モードで開いているファイルです。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
のstdinはパイプの読み取り端、または書き込み方向がシャットダウンされ(ksh93)、もう一方の端のcat
コンテンツを書き込むソケットペアfile
の一方の端になります。
stdinが通常ファイル(一時ファイルかどうか)である場合、それはシーク可能です。binary
先頭または末尾に移動したり、巻き戻しなどを行うこともできます。また、mmapしたり、ioctl()s
FIEMAP / FIBMAPのような操作を行ったりすることもできます(の<>
代わりに使用すると<
、穴を切り捨てたり、パンチしたりすることができます)。
一方、パイプとソケットのペアはプロセス間通信手段であり、データbinary
以外にできることはあまりありませんread
(ただしioctl()
、通常のファイルではなく、パイプ固有の操作がいくつかあります) 。
時間のほとんどは、それがために不足している能力だseek
(のようなアプリケーションは、パイプを扱うときに文句/失敗するが、それは通常のファイルではなく、ファイルの種類に有効な他のシステムコールのいずれかの可能性がありmmap()
、ftruncate()
、fallocate()
) 。Linuxでは、/dev/stdin
fd 0がパイプ上または通常のファイル上にあるときに開くときの動作にも大きな違いがあります。
シーク可能なファイルのみを処理できるコマンドは数多くありますが、その場合、通常は標準入力で開かれているファイルには対応していません。
$ 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
代わりにすでに親が開かれたFDを継承の(通常は0以外のFDに)それ自体を開きます。標準入力からzipファイルを読み取りません。stdinは、主にユーザーとの対話に使用されます。
binary
ターミナルエミュレーターで実行されている対話型シェルのプロンプトでリダイレクトせずに実行すると、シェルbinary
のstdinが親シェルから継承され、シェル自体は親からターミナルエミュレーターを継承し、読み取り+書き込みモードで開いているptyデバイス(のようなもの/dev/pts/n
)。
これらのデバイスもシークできません。したがって、binary
端末から入力を取得するときに問題なく動作する場合、問題はシークに関するものではない可能性があります。
その14がerrno(システムコールの失敗によって設定されるエラーコード)である場合、ほとんどのシステムではEFAULT
(Bad address)になります。read()
書き込み可能でないメモリアドレスに読み込むように求めた場合、システムコールは、そのエラーで失敗します。これは、ポイントからデータを読み取るfdがパイプまたは通常のファイルのどちらであるかには関係なく、一般にバグを示します1。
binary
おそらくその標準入力で開いているファイルのタイプを(withでfstat()
)判断し、通常のファイルでもttyデバイスでもない場合にバグに遭遇します。
アプリケーションの詳細を知らなくてもわかりにくい。以下の下でそれを実行するstrace
(またはtruss
/ tusc
システム上で同等のことは)私たちは、システムコールが、ここで失敗していることがあれば何であるか見るのを助けることができました。
1あなたの質問へのコメントでマシュー・イフェが想定しているシナリオは、ここでもっともらしい。彼を引用:
データを読み取るためのバッファサイズを取得するためにファイルの最後までシークし、シークが機能しないという事実を不適切に処理し、負のサイズを割り当てようとしています(不良なmallocを処理しない)。バッファを渡して、バッファに与えられた障害が無効であることを読み取ります。