Bashでサブシェルを呼び出すルールは何ですか?

Bashでサブシェルを呼び出すルールは何ですか?

サブシェルを生成するための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コマンドは、同じプロセス内のサブシェルを置き換えます。

つまり、基本的なケースは次のようになります。

  1. ( … )サブシェルを作成します。元のプロセスはとforkを呼び出しますwait。サブプロセスでは、これはサブシェルです。
    1. sleep子プロセスの子プロセスが必要な外部コマンドです。サブシェル呼び出しforkwait。子サブプロセスでは:
      1. 子サブプロセスは外部コマンド→を実行しますexec
      2. 最終コマンドが終了します→ exit
    2. waitサブシェルで実行されます。
  2. wait元のプロセスで完了しました。

最適化は次のとおりです。

  1. ( … )サブシェルを作成します。元のプロセスはとforkを呼び出しますwait。サブプロセス内では、次を呼び出すまでサブシェルですexec
    1. sleepこれは外部コマンドであり、プロセスが実行する必要がある最後の操作です。
    2. サブプロセスは外部コマンド→を実行しますexec
    3. 最終コマンドが終了します→ exit
  2. wait元のプロセスで完了しました。

呼び出し後に他のものを追加する場合は、これらのsleep最適化が発生しないようにサブシェルを保存する必要があります。

呼び出し前に他のものを追加すると最適化が行われますがsleep(kshはこれを実行します)、bashはそうではありません(この最適化は非常に保守的です)。

おすすめ記事