Learning Bash Bookには、サブシェルは環境変数やファイル記述子などのみを継承し、エクスポートされない変数は継承しないと記載されています。
$ var=15
$ (echo $var)
15
$ ./file # this file include the same command echo $var
$
私が知っているように、シェルは()用に2つのサブシェルを作成します および./file 、しかしなぜ()に サブシェルはvarを識別しますか エクスポートされておらず、./fileにありますが変数 識別されなかった場合
# Strace for ()
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f24558b1a10) = 25617
# Strace for ./file
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f24558b1a10) = 25631
straceを使おうとしました これがどのように発生するかを理解するために、驚くべきことに、bashはcloneシステムコールに同じ引数を使用することがわかりました。これは、()の両方のフォークされたプロセスを意味します。 および./file 親と同じプロセスアドレス空間を持つ必要があるので、なぜ()に ケースはサブシェルに表示される変数であり、./fileでは同じことは起こりません。 同じ引数がクローンシステムコールに基づいていますが?
承認された回答:
LearningBashBookは間違っています。サブシェルはすべての変数を継承します。 $$でも (元のシェルのPID)は保持されます。その理由は、サブシェルの場合、シェルはフォークするだけで新しいシェルを実行しないためです(逆に、./fileと入力すると、 、新しいコマンドが実行されます。新しいシェル。 strace出力で、execveを確認します。 および同様)。したがって、基本的には単なるコピーです(いくつかの文書化された違いがあります)。
注:これはbashに固有のものではありません。これはどのシェルにも当てはまります。