&6と/dev/fd/6の違いは何ですか?

&6と/dev/fd/6の違いは何ですか?

ファイル記述子6を読むには、<&6または</dev/fd/6(別名/proc/self/fd/6)を使用できます。多くの場合、両方とも同じように効果的です。ただし、対応するファイル記述子がソケットの場合、奇妙なことが起こります。たとえば、

$ bash -c 'ls -l /dev/fd/6;cat /dev/fd/6' 6</dev/tcp/localhost/12345
lrwx------ 1 michas michas 64 Jan 10 19:50 /dev/fd/6 -> socket:[315010]
cat: /dev/fd/6: No such device or address

これはls記述子が存在することを示します。しかし、このようにデータにアクセスすることは不可能です。使用すると、cat <&6すべてが正常に戻ります。

ファイル記述子にアクセスする2つの方法の違いは何ですか?

変数に数値が与えられた場合、記述子にアクセスするための良い方法はありますか? (</dev/fd/$fdはい、しかしそうでは<&$fdありません。)

(上記はLinuxでは見ることができますが、OpenBSDでは見ることはできません。 - ファイル記述子が通常の文字デバイスであるように見えます。)

ベストアンサー1

その理由は、/dev/fd/Linuxにはソケットを表すエントリからデータを読み取る実装がないためです。ここで推論に関する良い記事を見つけることができます。したがって、そのリンクを呼び出すことができるので、としてマークされますが、stat意図ls的に無効になります。

それでは、2番目の部分に進みます。なぜ動作しますかbash -c 'ls -l /dev/fd/6; cat <&6' 6</dev/tcp/localhost/12345?これは/proc、ファイルシステムではなくソケット/ファイルAPIを使用してソケットを読み取るためです。これが私が観察したものです:

  1. bash端末で実行されているインスタンスはfd 6を使用してソケットを作成します。
  2. 子プロセスがbash実行され、ソケットを 's'dup2(6, 0)に接続するために呼び出されます。catstdin
  3. dup2呼び出しが失敗しない場合は、catが読み取られますstdin

次のように再現して観察できます。

netcat -lp 12345    # in another terminal session (GNU netcat)
strace -f -e trace=open,read,write,dup2 bash -c 'ls -l /dev/fd/6; cat <&6' \
 6</dev/tcp/localhost/12345

サブプロセスがfd 6にアクセスできる理由がわからない場合は、bashファイル記述子がまだ存在しますfork閉じてマークされていない場合はexec閉じません。

おすすめ記事