ksh93如何避免命令替换中的派生


12

给定

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

炮弹往往需要制作两个叉子才能实现

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 

它失败了,但是不能管理整个管道。我想将其用于整个管道,可能将其带到其他shell。
PSkocik

3
只是为了进行完整性检查,您已经ksh安装了吗?当我运行您的代码时,会得到0我没有安装的任何外壳的信息
Eric Renouf

1
@EricRenouf大声笑,是的。它也可以做。;)
PSkocik

回答者可能需要阅读stackoverflow.com/questions/14686872
JdeBP '16

Answers:


13

Ksh93在避免分叉方面做了很多工作。我不知道它怎么知道如何处理第一种情况,因为这truss表明它只调用一个write(2)最终结果的调用。

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

我可以说的是,我去年重写了“ Bourne Shell”的解析器和解释器,主要是减少了分叉的数量,并通过vfork()调用替换了许多分叉。当前,这使得Bourne Shell成为仅次于ksh93的第二快的Shell。您可能也想运行测试bosh

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

只要有(cmd)子外壳,ksh93就会使用此方法。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.