サブシェルを生成するためのBashルールを誤解したようです。私は角括弧が常に独自のプロセスとして実行されるサブシェルを生成すると思いました。
しかし、これは本当ではないようです。コードスニペットA(下)では、2番目のsleep
コマンドは別のシェル(pstree
他の端末によって決定されます)では実行されません。しかし、コードフラグメントBでは、2番目のコマンドsleep
はする別のシェルで実行します。これらのスニペット間の唯一の違いは、2番目のスニペットには角かっこ内に2つのコマンドがあることです。
サブシェルの作成規則を説明できる人はいますか?
コードスニペットA:
sleep 5
(
sleep 5
)
コードピースB:
sleep 5
(
x=1
sleep 5
)
ベストアンサー1
括弧は常にサブシェルを開始します。何が起こるかは、bashがこれがsleep 5
そのサブシェルによって実行された最後のコマンドであることを検出してexec
代わりに呼び出すことです。fork
+exec
。このsleep
コマンドは、同じプロセス内のサブシェルを置き換えます。
つまり、基本的なケースは次のようになります。
( … )
サブシェルを作成します。元のプロセスはとfork
を呼び出しますwait
。サブプロセスでは、これはサブシェルです。sleep
子プロセスの子プロセスが必要な外部コマンドです。サブシェル呼び出しfork
とwait
。子サブプロセスでは:- 子サブプロセスは外部コマンド→を実行します
exec
。 - 最終コマンドが終了します→
exit
。
- 子サブプロセスは外部コマンド→を実行します
wait
サブシェルで実行されます。
wait
元のプロセスで完了しました。
最適化は次のとおりです。
( … )
サブシェルを作成します。元のプロセスはとfork
を呼び出しますwait
。サブプロセス内では、次を呼び出すまでサブシェルですexec
。sleep
これは外部コマンドであり、プロセスが実行する必要がある最後の操作です。- サブプロセスは外部コマンド→を実行します
exec
。 - 最終コマンドが終了します→
exit
。
wait
元のプロセスで完了しました。
呼び出し後に他のものを追加する場合は、これらのsleep
最適化が発生しないようにサブシェルを保存する必要があります。
呼び出し前に他のものを追加すると最適化が行われますがsleep
(kshはこれを実行します)、bashはそうではありません(この最適化は非常に保守的です)。