我知道外部命令是通过创建单独的进程在 shell 中运行的,但是当内置命令在 shell 中运行时到底会发生什么?
它们是作为函数执行的,还是 shell 创建一个新线程来执行它们?
答案1
对于您的具体示例,有一个 function cd_builtin
,它在builtins/cd.def(在bash源代码中)中定义。它通常cd
通过调用该函数来完成。但如果您在管道中使用它,它可能会首先分叉——例如,cd / | echo
分叉并调用cd_builtin
子级。您还可以通过目录实际上没有更改来注意到这一点:
anthony@Zia:~$ cd /tmp/
anthony@Zia:/tmp$ cd / | echo -n
anthony@Zia:/tmp$ cd /
anthony@Zia:/$
请注意,只有当我不通过管道传输时,目录才会发生变化cd
。
答案2
根据定义,内置命令在主可执行文件内执行,而不是在不同的程序中执行。
所有 shell 命令都是同步的:shell 在执行下一个命令之前等待命令完成。当运行外部命令时,shell 必须创建一个单独的进程来运行该命令,并等待它退出。运行内置命令时,无需创建新的执行线程:该命令在主线程内执行。
我不认为任何常见的 shell 在其内部设计中使用线程。 Shell 功能与传统的每进程单线程 Unix 模型密切相关,因此线程可以解决 shell 设计中的任何问题。
每个内置函数很可能都是由 shell 源代码中某个级别的函数实现的。
答案3
我认为它们作为可执行文件空间内的函数运行bash
。评论里有一条高级 Bash 脚本编写指南其声明如下:
摘抄
内置命令是 Bash 工具集中包含的命令,实际上是内置的。这要么是出于性能原因——内置命令比外部命令执行得更快,而外部命令通常需要分叉1一个单独的进程——或者因为特定的内置函数需要直接访问 shell 内部。