ksh93はコマンド置換でフォークをどのように回避しますか


12

与えられた

cmd='fun(){ echo "$@";  }; fun $(fun $(fun hi))'

シェルはそれを実現するために2つのフォークを作る必要がある傾向があります

strace-f(){ strace -f "$@" 2>&1; }; 
for sh in dash bash zsh ksh; do 
    printf "$sh\t" ; strace-f $sh -c "$cmd"  |grep -e clone -e fork -c;
done

ksh一度もフォークせずに英雄的に作成する場合を除きます:

dash    2
bash    2
zsh     2
ksh     0

それはどうやって?


編集:

パイプがスローされると、次のようになります。

cmd='fun(){ echo "$@"| echo "$@";  }; fun $(fun $(fun hi))'

出力:

dash    11
bash    10
zsh     5
ksh     3 

ただし、パイプライン全体でこれを管理することはできません。パイプライン全体でこれを可能にし、おそらく他のシェルに持ち込みたいと思います。
PSkocik

3
健全性チェックのためだけに、kshインストールしましたか?私はあなたのコードを実行すると、私が得る0私がインストールされていない任意のシェルのために
エリックRenouf

1
@EricRenouf Lol、そうです。そして、それも同様に行います。;)
PSkocik

回答者はstackoverflow.com/questions/14686872を読みたいかもしれません。
-JdeBP

回答:


13

Ksh93は、フォークを回避するために多くのことを行います。最初のケースを処理する方法をどのように知っているのかわかりません。これは、最終結果でtruss1つのwrite(2)呼び出しのみを呼び出すことを示しています。

Davidはmacro.cのコマンドをスキャンし、内部で「エコー」を処理できることを知っている可能性があります。

私が言えることは、昨年、「Bourne Shell」のパーサーとインタープリターを書き直し、主にフォークの数を減らし、多くのフォークをvfork()呼び出しに置き換えたことです。これにより、現在、Bourne Shellはksh93に次いで2番目に速いシェルになっています。同様にテストを実行することもできますbosh

ところで:ksh93は一般的にフォークを避けます。これは、以前のすべてのグローバル変数を含む構造を実装します。これにより、「グローバル」変数構造ポインタの異なるインスタンスで呼び出された場合、シェルコードが再入可能になります。

この方法は、(cmd)サブシェルがある場合は常にksh93によって使用されます。

この書き換えの理由は、DavidがラップトップでWin-DOSを使用しており、遅いCygwinが好きではなかったため、UWINを作成し、Win-DOSでksh93を直接使用しているためです。fork()Win-DOS にはないので、彼は新しいソリューションを見つける必要がありました...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.