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に固有のものではありません。これはどのシェルにも当てはまります。