デフォルトでは、ファイル記述子はexec関数で開いたままです。記述子0-2の場合、この利点を理解できます。しかし、他の記述子を開いたままにする実際のユースケースはありますか?この事実に依存する実際的な適用はありますか?
答え1
実行されたコマンドにfdを渡したくない場合は、ファイル記述子にフラグを設定できます(open()
:O_CLOEXEC以降:FD_CLOEXEC)。fcntl()
コマンドを実行するには、内部ファイル記述子を使用して実行する必要があります。
たとえば、シェルは次のことをksh93
行います。exec 3< some-file
別のシェルまたはfdを使用して開いた場合は、fd:を望ましくない、またはアクセスしたくない場合は手動{ cmd1; cmd2; } 3< file
で閉じる必要があります。cmd1
cmd2
{cmd1 3<&-; cmd2; } 3< file
これは良い習慣ですが、一般的に従わなくても問題にならないので、常に従うわけではありません。。
さて、この機能は役に立ちますか?はい、いくつかのコマンドがそれに依存します。
一部のコマンドは、呼び出し元が開いたファイル記述子を引数として使用します。心に浮かぶいくつかの例は次のとおりです。
xterm
そしてその-S
オプションqemu
いろいろな仕事のためにflock
(送信者fdのファイルをロックします)- コマンドはオプション
test
とも呼ばれます(最近、ほとんどのBourneに似たシェルにはユーティリティが組み込まれていますが、まだ実行できるコマンドがあります)。[
-t
test
test
dialog
ユーザー入力、ユーザー出力とエラー、呼び出し元の入力と出力にはファイル記述子が必要なため、追加のfdを使用できます。gpg
あるいは、openssl
パスワードなどの情報を渡すためにファイル記述子を指定することもできます。
たくさんあります助ける人ユーティリティ(例:実装するそれはおそらく、それに依存するsetuid / setgid実行可能ファイルを使用して他のユーザーまたはグループで実行されるコマンドの一部です。
プロセスの交換はそれに依存します。
では、diff <(cmd1) <(cmd2)
2つのファイル記述子(パイプ用)がdiffに渡され、diff
引数として渡された特殊な/ dev / fd / nを介してそれらを開いてアクセスします。
プロセスの交換がないシェルの場合は、以下を手動で実行できます。
cm1 | { cmd2 | diff /dev/fd/3 -; } 3<&0
答え2
TinyMUSHとおそらく多くの兄弟やサブコードライブラリはexecのこの機能を使って大きな効果をもたらします。サーバーを再起動するコマンドを実行して、ユーザー接続を維持しながら新しいバイナリにアップグレードできます。
これは、ファイル記述子を含む接続された各ユーザーに関する情報を含む小さなデータベースを作成することによって行われます。 TinyMUSHの新しく実行されたコピーは、再起動データベースを読み取って接続されているユーザーに関する知識を復元し、中断された部分から続きます。
最終結果:新機能がリリースされ、ユーザーには短い一時中ですが表示されます。
Nginxが実行することは、接続を切断せずにバイナリアップグレードを実行するのと多少似ています。
答え3
接続されたソケットはこの方法で子プロセスに渡すことができます。たとえば、着信接続を受け入れるネットワークサーバーは、その接続処理をまったく異なるプロセスに転送できます。
よりinetdソースコード、一般的な例を見てみましょう。
答え4
私は記述子2以外のものを伝えることができる真の普遍的なプログラムがないと思います。その場合、exec()されたプログラムはハードコードされたファイル記述子番号を想定する必要があります。
write(3, ...);
または
fp = fdopen(3, "r");
これは悪いコーディング習慣です。親と子プログラムを厳密に管理し、他人が干渉できない場合にのみ意味があります。