組み込みコマンドを使用するとシェルがフォークされますか?

組み込みコマンドを使用するとシェルがフォークされますか?

コマンドを実行すると、type typestdoutの結果が表示されます。

次に、次のコマンドを試してみます。

type type > abc.txt

abc.txtしたがって、このコマンドが同じプロセス(bash自体)で実行されると、ファイル記述子1はポイントしますabc.txtabc.txtabc.txt

ただし、結果は常に標準出力として印刷されます。これは、シェルの組み込みがフォークされたプロセスで実行されていることを意味しますか?

ベストアンサー1

通常、コマンドをリダイレクトするためにシェルがしなければならないのは、子プロセスをフォークして子プロセスだけにリダイレクトしてから(親ファイル記述子は影響を受けません)、その中でコマンドを実行することです(親は待っている間)。 。

組み込みコマンド(または複合コマンドまたは関数...)の場合、フォークや実行はありません。ただし、リダイレクトされた組み込みコマンドが終了すると、ファイル記述子は以前の状態に戻ります。

この目的のために、シェルはリダイレクトを実行する前に、リダイレクトされたファイル記述子のコピーを別のファイル記述子に保存し、そのファイル記述子をO_CLOEXECフラグとして表示します(組み込み機能が同じコマンドをeval実行する場合command)。返されると、シェルはファイル記述子を復元します。

たとえば、次のコマンドを実行すると、次のようになります。

strace sh -c 'echo test > /dev/null; :'

表示される内容(関連項目のみを含む):

  • open("/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3:リダイレクトするファイルを開きます。
  • fcntl(1, F_DUPFD, 10) = 10:生のstdoutを最初の利用可能なfd> = 10(ここでは10)にコピーします。
  • fcntl(10, F_SETFD, FD_CLOEXEC) = 0:O_CLOEXEC フラグを設定します。
  • dup2(3, 1) = 1:リダイレクトされたファイルを標準出力に設定します。
  • close(3) = 0:もう必要ありません。
  • write(1, "test\n", 5) = 5:echo は実行され、標準出力に "test\n" を書き込みます (現在 /dev/null にリダイレクトされます)。
  • dup2(10, 1) = 1: 標準出力の復元
  • close(10) = 0:不要になったfd 10を閉じます。

Bourneシェルで複合コマンドをリダイレクトすると、ブランチが発生します(thenにa=0; { a=1; echo "$a"; } >&2; echo "$a"示されています)。この問題を解決するには、実際に上記の作業を手動で実行する必要があります。10

変える

while cmd1; do cmd2; i=`expr "$i" + 1`; done > file

あなたはこれをしなければなりません:

exec 3>&1 > file
while cmd1 3>&-; do cmd2 3>&-; i=`expr "$i" + 1 3>&-`; done
exec >&3 3>&-

( 3>&-fd には O_CLOEXEC フラグがないため、各コマンドごとに 1 つずつ)

以前のバージョンのBourneシェルでは、組み込みコマンドをリダイレクトできませんでした。 pdp11をエミュレートするUnix V7では:

$ eval a=1 > /tmp/x
illegal io
$ read a < /etc/passwd
illegal io

おすすめ記事