linux - 为什么在分组命令中执行简单命令不会fork子shell进程,而复合命令会这样做
问题描述
我知道分组命令(command-list)
会创建一个子shell 环境,并且每个列出的命令都在该子shell中执行。但是如果我在分组命令中执行一个简单ps
的命令,(使用命令输出进程),那么没有子shell进程输出。但是,如果我尝试在分组命令中执行命令列表(复合命令),则会输出一个子shell 进程。为什么会产生这样的结果?
- 在分组命令中执行一个简单命令(仅一个
ps
命令)的测试:
具有以下输出:[root@localhost ~]# (ps -f)
UID PID PPID C STIME TTY TIME CMD root 1625 1623 0 13:49 pts/0 00:00:00 -bash root 1670 1625 0 15:05 pts/0 00:00:00 ps -f
- 在分组命令
中执行复合命令(命令列表)的另一个测试:
具有以下输出:[root@localhost ~]# (ps -f;cd)
UID PID PPID C STIME TTY TIME CMD root 1625 1623 0 13:49 pts/0 00:00:00 -bash root 1671 1625 0 15:05 pts/0 00:00:00 -bash root 1672 1671 0 15:05 pts/0 00:00:00 ps -f
我测试了很多其他命令(复合命令和简单命令),但结果都是一样的。我想即使我在分组命令中执行一个简单的命令,bash
也应该分叉一个子shell进程,否则它无法执行命令。但是为什么我看不到呢?
解决方案
Bash 优化了执行。它检测到只有一个命令在(
)
组内并调用fork
+exec
而不是fork
+ fork
+ exec
。这就是为什么您bash
在进程列表中看到的进程更少的原因。( sleep 5 )
当使用需要更多时间来消除时序的命令时,更容易检测到。此外,您可能想在 unix.stackexchange 上阅读此线程。
我认为优化是execute_cmd.c
在execute_in_subshell()
函数内部的某个地方完成的(我添加的箭头>
):
/* If this is a simple command, tell execute_disk_command that it
might be able to get away without forking and simply exec.
>>>> This means things like ( sleep 10 ) will only cause one fork
If we're timing the command or inverting its return value, however,
we cannot do this optimization. */
在execute_disk_command()
函数中我们还可以阅读:
/* If we can get away without forking and there are no pipes to deal with,
don't bother to fork, just directly exec the command. */
推荐阅读
- active-directory - 用于过滤 AD 中的内置或默认 OU 的 LDAP 属性
- javascript - 为什么 webpack 4 包含单个命名导入的整个文件?
- php - PHP:basename 在特殊字符上没有按预期工作
- python - 分块使用加速器数据集
- java - 双打四舍五入到最接近的整数的问题
- android - 使用数据绑定将viewmodel绑定到recyclerview item.xml,android?
- vue.js - 是否可以仅在需要的地方而不是在 nuxtjs 中的 nuxt.config.js 中实现包含脚本
- python - 并行应用并不比常规应用 pyhon 快
- antlr4 - 为什么 antlr 规则不会生成一个好的解析树?
- checkbox - 同位素:组合多个复选框和搜索框过滤