シェルが起動する前に/proc/self/fd/0にシリアルセッションに書き込み可能なビットがないのはなぜですか?

シェルが起動する前に/proc/self/fd/0にシリアルセッションに書き込み可能なビットがないのはなぜですか?

非常に古いバージョンを使用しているプログラムを見つけましたラインノイズ図書館。次のようにすべてのwrite()作業が完了しましたSTDIN_FILENO

write(STDIN_FILENO,prompt,plen)

write失敗し、-1を返し、errnoに設定されますEBADF。対話式で起動する前に、システムの起動時に順次実行されるCプログラムを作成しました/etc/init.d/rcS。 Cプログラムはディレクトリをリストし、出力は次のようになります。Busybox initsh/proc/self/fd

l-wx------    1 root     root          64 Jan  1 00:00 2 -> /dev/console
l-wx------    1 root     root          64 Jan  1 00:00 1 -> /dev/console
lr-x------    1 root     root          64 Jan  1 00:00 0 -> /dev/console

ご覧のとおり、0ビットがw設定されていないため、これは失敗しているようですwrite。しかし、sh通常のシェルが起動した後:

lrwx------    1 root     root          64 Jan  1 00:00 2 -> /dev/ttyS0
lrwx------    1 root     root          64 Jan  1 00:00 1 -> /dev/ttyS0
lrwx------    1 root     root          64 Jan  1 00:00 0 -> /dev/ttyS0

0がw設定されました。なぜこれが起こるのですか?

答え1

複数の端末装置を持つことができるからです。

したがって、具体的にはgettyパラメータと呼ばれます。ttyS0したがって、独自のコードを使用してすべてのFDを初期化します。これはttyを一度開いて/dev/consoleからFDを参照するのと同じです。initgettyO_RDWRdup

明らかな理由が見えます。パスワード次のように動作します。 stdinを使って呼び出すagettyこともできます。-したがって、常に使用するのがdup()最も簡単な実装です。

このオプションがなぜサポートされるのかわかりません。標準システムVは必ずしもこれを使用またはサポートしているわけではありませんinittab。と一致するようですBSDで使用される以前の方法ここで、initターミナルデバイスはパラメータの代わりに開いたFDに渡されます。従来の方法はinitすべてのFDを初期化することでした(協会stderr、次のバージョンに追加された2つのFDを参照してください)。

busyboxを指定するように質問を編集し、cttyhackが言及されているので、busyboxの場合、明らかな説明は「コードを小さくする」です。これは歴史的なUnixコードの主な特徴でもあります。

関連情報