简体   繁体   English

Will()构造总是启动一个子shell?

[英]Will () construct always start a subshell?

Current shell is 目前的外壳是

$ echo $$
23173

Note the parent of ps is current shell 请注意ps的父级是当前shell

$ ( ps -o pid,ppid,cmd )
  PID  PPID CMD
 8952 23173 ps -o pid,ppid,cmd
23173 23169 bash

But here , the parent of ps is the subshell (bash) 但是在这里,ps的父是子shell(bash)

$ ( echo hello ; ps -o pid,ppid,cmd )
hello
  PID  PPID CMD
 8953 23173 bash
 8954  8953 ps -o pid,ppid,cmd
23173 23169 bash

Is bash doing optimizations ? bash在做优化吗? How come an extra echo made the the difference and spawned a subshell in 3rd case ? 为什么一个额外的回声会产生差异并在第三种情况下产生一个子壳?

Yes, what you're seeing is an optimization. 是的,您所看到的是优化。 Technically, the (…) construct always starts a subshell, by definition. 从技术上讲, (…)构造总是按照定义启动子shell。 Most of the time, the subshell runs in a separate subprocess. 大多数情况下,子shell在一个单独的子进程中运行。 This ensures that everything done in the subshell stays in the subshell. 这可确保子shell中完成的所有操作都保留在子shell中。 If bash can guarantee this isolation property, it's free to use any implementation technique it likes. 如果bash可以保证这种隔离属性,它可以自由使用它喜欢的任何实现技术。

In the fragment ( ps -o pid,ppid,cmd ) , it's obvious that nothing can influence the parent shell, so there's an optimization in bash that makes it not fork a separate process for the subshell. 在片段( ps -o pid,ppid,cmd ) ,很明显没有任何东西可以影响父shell,因此bash中的优化使得它不会为子shell分叉一个单独的进程。 The fragment ( echo hello ; ps -o pid,ppid,cmd ) is too complex for the optimizer to recognize that no subshell is needed. 片段( echo hello ; ps -o pid,ppid,cmd )太复杂,优化器无法识别不需要子shell。

If you experiment with ksh , you'll notice that its optimizer is more aggressive. 如果你试验ksh ,你会发现它的优化器更具侵略性。 For example, it doesn't fork a subprocess for ( echo hello ; ps -o pid,ppid,cmd ) either. 例如,它不会为( echo hello ; ps -o pid,ppid,cmd )分叉子( echo hello ; ps -o pid,ppid,cmd )

A subshell consisting of a single simple command instead of a list or pipeline of more than one command could be implemented by simply "execing" the command, ie replacing the subshell with the process for the command called. 可以通过简单地“执行”命令来实现由单个简单命令而不是多个命令的列表或管道组成的子shell,即用所调用命令的进程替换子shell。 If the subshell is more complex then a simple exec is not possible, the subshell must stay around to manage the command sequence. 如果子shell更复杂,则不可能使用简单的exec,子shell必须保持不变以管理命令序列。

From your diagnostics it's impossible to tell the difference between a bash optimization where a subshell consisting of a simple command is optimized to a "direct" fork and exec of the called command or a fork of a subshell followed by an exec of the command called. 从您的诊断中,无法区分bash优化,其中由简单命令组成的子shell优化为“直接”fork和被调用命令的exec或子shell的fork,后跟被调用命令的exec。 This isn't surprising as the difference is (almost?) entirely academic. 这并不奇怪,因为差异(几乎?)完全是学术性的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM