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

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

给定

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

shell 往往需要创建 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 

答案1

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

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

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

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

只要存在子 shell,ksh93 就会使用此方法(cmd)

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

相关内容