子 shell 与子 shell 相同吗

子 shell 与子 shell 相同吗

有这两个名字:a子外壳和一个子壳

是的,子进程将通过以下任一方式启动:

sh -c 'echo "Hello"'
( echo "hello" )
echo "$(echo "hello")
echo "hello" | cat

都是等价的并且具有相同的名称吗?所有人都具有相同的属性吗?


POSIX有这个定义:

shell执行环境包括......

但上面链接的最后一段是这样的:

子 shell 环境应创建为 shell 环境的副本,但未被忽略的信号陷阱应设置为默认操作。

特别是:

命令替换、用括号分组的命令以及异步列表应在子 shell 环境中执行。此外,多命令管道中的每个命令都位于子shell环境中; ....

sh -c 'echo "Hello"'包含在那里,那也应该被称为子shell吗?

答案1

一个子shell重复项现有的外壳。它具有相同的变量、相同的函数、相同的选项等。在幕后,使用以下命令创建了一个子 shellfork系统调用²;子进程继续执行预期的操作,而父进程则等待(例如,$(…))或继续其生命(例如,… &)或以其他方式执行预期的操作(例如,… | …)。

sh -c …不创建子shell。它启动另一个程序。该程序恰好是一个 shell,但这只是一个巧合。该程序甚至可能是一个不同的 shell(例如,如果您sh -c …从 bash 运行,并且sh是 dash),即一个完全不同的程序,只是其行为恰好有显着的相似之处。在幕后,启动外部命令(sh或任何其他命令)会调用fork系统调用,然后execve系统调用代替子进程中的 shell 程序由另一个程序执行(此处sh)。

¹包括$$,但不包括一些特定于 shell 的变量,例如 bash 和 mksh 的BASHPID
²至少,这是传统且通常的实现方式。如果 shell 能够模仿行为,那么它们就可以优化分叉。看“子shell”和“子进程”之间的确切区别是什么?

相关手册页:叉子(2),执行(2)

答案2

子 shell 环境不需要存在于单独的进程中,它只需要复制当前的执行环境。这ksh93是通过virtual sub-shell不调用fork().这使得 ksh93 在像 一样的古老平台上非常快Win-DOS,而Win-DOS分叉时却非常慢。

sh -c cmd另一方面,使用默认 shell 创建一个新进程,该进程不需要与当前的交互式 shell 相同。

即使sh当前 shell 相同,也不会复制执行环境,因此不会创建sub-shell.

相关内容