正木です。
ご回答ありがとうございます。

On Tue, 22 Oct 2019 15:21:14 +0900
Kazuhiro NISHIYAMA <zn / mbf.nifty.com> wrote:

> 西山和広です。
> 
> On Thu, 12 Sep 2019 22:29:45 +0900,
> MASAKI Haruka wrote:
>  [...]  
> 
> ファイルディスクリプタが引き継がれていないというのはどうやって確認していますか?
> たぶん親プロセスがバッファの長さまで読み込んで (ファイルが短いので EOF まで)、
> その状態のファイルディスクリプタが継承されているだけではないでしょうか。
> 
gets→cat→readの順にやって「catは何も読み込めず、readは読み込める」ことからそのように判断していました。
あとは
% ruby -e 'STDIN.gets' -e 'fork { exec("cat", "-n") }'
とすると1行読むとプロンプトが返ってしまうのも理由でした。

が、実際に大きいテキストファイル(13MBほど)を用意して試してみると期待通りに動作することを確認できました。
また、sed -qを使っても同様に大きいファイルであれば期待通りに動作することを確認しました。
納得です。

> sysread のようにシステムコールで直接読み込めば読み込み過ぎないのを確認できます。
> 
> % (ruby -e 'gets' -e 'exec(*%w"head -n 1")' ) < /etc/hosts
> % (ruby -e 'STDIN.sysread(3)' -e 'exec(*%w"head -n 1")' ) < /etc/hosts
> .0.0.1  localhost
> % (ruby -e 'gets' -e 'exec("readlink", "/proc/self/fd/0")' ) < /etc/hosts
> /etc/hosts
> 
>  [...]  
> 
> pos の中で lseek しているので、ファイルディスクリプタの方も
> 読み込み位置が戻っているようです。
> 

こちらも理解できました。ありがとうございます。
lseekする理由はバッファに溜め込んだ分を打ち消すため、でしょうか…

解決しました。ありがとうございます。

> 
> -- 
> |ZnZ(ゼット エヌ ゼット)
> |西山和広(Kazuhiro NISHIYAMA)