子 shell 的生命在创建后不久就结束了吗?即,它的资产是否会被将要在其中运行的流程所取代?假设我们在 bash 中运行
grep -r "something"
,所以我们的 shell(bash) 创建了一个子进程,它最初不是“grep”,它一开始只是 bash 本身的一个分支,但由于我们最终希望“grep”成为运行时,子 shell 的资产将“迅速地”被 grep 进程取代。 (在图中:Shell --->“Child Shell”(寿命短?)---> Process)所有 shell 命令都会创建子 shell 吗?例如,运行像“ls -l”这样简单的命令是否也会在一小段时间内创建一个子进程?因为同样的原因(如1中所解释的)再次适用于此,“ls”本身就是一个程序,当它运行时,我们不希望它的进程取代我们自己的shell进程。
如果 2 的答案是“是”,这是否意味着运行包含许多 shell 命令的 shell 脚本将导致创建“许多”子 shell 和进程?
答案1
区分进程及其内部运行的内容非常重要(您的问题表明您意识到了这种区别)。每当在一个进程中运行的给定程序想要运行另一个程序时,它有两个选择:它可以要求操作系统用新程序替换当前进程中的它(exec
函数族),或者它可以要求操作系统创建一个新进程(功能fork
然后在该过程中要求操作系统在新进程中用新程序替换它。
当您
grep
从 shell 运行时,shell 通常希望在之后重新获得控制权,因此它会分叉,grep
在分叉中运行,并等待分叉进程完成。所以,是的,分叉中的 shell 是短暂的,但是在大多数当前操作系统上,在分叉中“创建”shell 的“资产”根本不需要花费太多(感谢写入时复制机制)。这同样适用于
ls -l
交互式 shell。然而,在某些情况下,shell 会替换自身而不是分叉;看为什么 bash 不为简单命令生成子 shell?了解详情。运行 shell 脚本将为运行脚本的 shell 创建一个进程,为 shell 中的每个外部命令创建一个进程,还可能为某些 shell 结构创建子 shell。
创建流程很便宜,但exec
成本却更低;这就是人们经常关心限制正在使用的进程数量的部分原因。另外两个原因(可能更重要)是,启动一个程序涉及该程序启动的成本,并且通常涉及重复整个过程的某些部分(在具有后者的系统上比较find ... -exec grep
和,或者多次调用等。到单个或)。一旦由于过度依赖外部命令而开始在 shell 脚本中遇到速度问题,这通常表明是时候使用功能更强大的编程环境了,该环境将允许在不涉及其他程序的情况下进行更多数据处理。grep -r
grep
sed
sed
awk