ksh93 如何避免命令替换中的分叉

PSk*_*cik 12 shell ksh fork command-substitution optimization

给定的

cmd='fun(){ echo "$@";  }; fun $(fun $(fun hi))'
Run Code Online (Sandbox Code Playgroud)

贝壳往往需要制作 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
Run Code Online (Sandbox Code Playgroud)

除了ksh英勇地使它没有分叉一次:

dash    2
bash    2
zsh     2
ksh     0
Run Code Online (Sandbox Code Playgroud)

它是如何做到的?


编辑:

下面是它如何随着一个管道的插入而下降:

cmd='fun(){ echo "$@"| echo "$@";  }; fun $(fun $(fun hi))'
Run Code Online (Sandbox Code Playgroud)

输出:

dash    11
bash    10
zsh     5
ksh     3 
Run Code Online (Sandbox Code Playgroud)

sch*_*ily 13

Ksh93 做了很多工作来避免分叉。我不知道它是如何知道如何处理第一种情况的,因为 atruss表明它只调用一个write(2)具有最终结果的调用。

可能是 David 扫描了 macro.c 中的命令,知道他可以在内部处理“echo”。

我能说的是,我去年重写了《Bourne Shell》的解析器和解释器,主要是减少了fork的数量,用vfork()调用代替了很多fork 。这使得 Bourne Shell 成为仅次于 ksh93 的第二快的 shell。您可能还想运行您的测试bosh

顺便说一句:ksh93 通常避免分叉。它实现了一个包含所有先前全局变量的结构,如果使用“全局”变量结构指针的不同实例调用它,这会使 shell 代码可重入。

每当有(cmd)子shell时,ksh93 都会使用此方法。

这次重写的原因是David在他的笔记本电脑上使用的是Win-DOS,他不喜欢Cygwin的慢,所以他写了UWIN,直接在Win-DOS上使用ksh93。由于fork()Win-DOS上没有,他需要找到一个新的解决方案......