読者です 読者をやめる 読者になる 読者になる

bekkou68の日記

開発しているサービス, IT技術, 英語など。

『Working with Unix Processes』の Processes Have File Descripters を読みました

Unix 勉強会

メモ

Unix の思想の一つは「すべてがファイルである」。テキストファイルもデバイスもソケットもファイル。ファイルディスクリプタはOSがファイルを識別するための識別子である。なお、関連のないプロセス間でファイルディスクリプタは共有されない。
Ruby ではファイルディスクリプタを File#fileno で取得できる。
ファイルディスクリプタはネットワークプログラミングでつかうソケットとかパイプのコアな部分。

試したこと

予約されている fileno の謎

irb で適当なファイルを開いて fileno したら 5 でした。

$ file = File.open('/etc/hosts')
 => #<File:/etc/hosts>
$ file.fileno
 => 5

STDIN、STDOUT、STDERR の fileno はそれぞれ 0, 1, 2 でした。

$ STDIN.fileno
 => 0 
$ STDOUT.fileno
 => 1 
$ STDERR.fileno
 => 2 

じゃあ、3 と 4 の fileno は何をしているのか? と気になりました。

$ File.open(3)
ArgumentError: The given fd is not accessible because RubyVM reserves it
...
$ File.open(4)
ArgumentError: The given fd is not accessible because RubyVM reserves it
...

どうやら 3, 4 は RubyVM で予約されているようです。何に使っているのかなあ。

fileno はどこまで?

試してみたら 255 くらいまでいけてエラーが出ました。

$ 1000.times {|i| tmpfile = File.open('/etc/passwd'); self.instance_variable_set("@filetest#{i}", tmpfile); puts tmpfile.fileno; sleep 0.03}
5
6
...
254
255
Errno::EMFILE: Too many open files - /etc/passwd
...

こういうのって、OS の制約とかあったりするのかな? と思ったのですが、どうやら次の章で解説があるみたいです。

Ruby ではファイルディスクリプタを指定してファイルを開けるみたい
$ File.open(0).each {|a| puts a}
a
a
b
b

おおお。STDIN から入力を求められて cat みたいになった!

STDERR だけ close しても落ちない謎
$ STDIN.close # irb が落ちる
$ STDOUT.close # irb が落ちる
$ STDERR.close # irb が落ちない! 謎。。

フレーズ

  • misnomer: 誤った表現