web-dev-qa-db-ja.com

サブシェルは子シェルと同じです

この2つの名前があります。asubshel​​lとachild-Shellです。

はい、子プロセスは次のいずれかによって開始されます:

sh -c 'echo "Hello"'
( echo "hello" )
echo "$(echo "hello")
echo "hello" | cat

すべて同等で、同じ名前を共有していますか?すべて同じプロパティを共有していますか?


POSIX この定義があります

シェル実行環境は...で構成されています。

しかし、上記のリンクの最後の段落にはこれがあります:

サブシェル環境は、無視されないシグナルトラップがデフォルトのアクションに設定されることを除いて、シェル環境の複製として作成されます。

そして特に:

コマンド置換、括弧でグループ化されたコマンド、および非同期リストは、サブシェル環境で実行されます。さらに、マルチコマンドパイプラインの各コマンドはサブシェル環境にあります。 ....

sh -c 'echo "Hello"'はそこに含まれていません。それもサブシェルと呼ばれるべきですか?

11
user79743

サブシェルは、既存のシェルを複製します。同じ変数¹、同じ関数、同じオプションなどがあります。内部では、サブシェルが fork システムコール²で作成されます。子プロセスは、親が待機している間(たとえば、$(…))、またはその存続期間中に継続して(たとえば、… &)、またはそれ以外の場合に期待されることを実行します。 (例:… | …)。

sh -c …はサブシェルを作成しません。別のプログラムを起動します。そのプログラムはたまたまシェルですが、それは単なる偶然です。プログラムは別のシェル(たとえば、sh -c …をbashから実行し、shがダッシュである場合)、つまり、動作がかなり類似している完全に異なるプログラムの場合もあります。内部的に、外部コマンド(shまたはその他のコマンド)を起動すると、forkシステムコールが呼び出され、次に execve システムコールreplaceサブプロセス内のシェルプログラムを別のプログラム(ここではsh)に置き換えます。

¹ $$を含みますが、bashやmkshのBASHPIDなどのシェル固有の変数をいくつか除外します。
² 少なくとも、これは従来の通常の実装です。シェルは、振る舞いを模倣できればフォークを最適化できます。

関連するmanページ: fork(2)execve(2)

サブシェル環境は、別のプロセスに存在する必要はありません。現在の実行環境を複製する必要があるだけです。 _ksh93_では、これはfork()を呼び出さない_virtual sub-Shell_メカニズムによって行われます。 _Win-DOS_はフォークで非常に遅いので、これは_Win-DOS_のような古いプラットフォームでksh93を非常に高速にします。

反対側の_sh -c cmd_は、現在の対話型シェルと同じである必要がないデフォルトのシェルで新しいプロセスを作成します。

shと現在のシェルが同一であっても、これは実行環境を複製しないため、_sub-Shell_は作成されません。

1
schily