子外壳与子外壳是否相同


11

有两个名称:subshel​​lchild-shell

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

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

是否都相同并具有相同的名称?所有共享相同的属性吗?


POSIX 具有以下定义

Shell执行环境由...组成。

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

子外壳程序环境应作为外壳程序环境的副本创建,但不忽略的信号陷阱应设置为默认操作。

特别是:

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

其中sh -c 'echo "Hello"'不包含,也应该称为subshel​​l吗?

Answers:


14

子shell 复制了现有的shell。它具有相同的变量fork¹ ,相同的功能,相同的选项等。在幕后,使用系统调用² 创建了一个子外壳;当父进程等待(例如$(…))或继续其生命(例如… &)时,子进程继续执行预期的操作,否则父进程将继续执行预期的操作(例如… | …)。

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

¹ 包括$$但不包括某些特定于shell的变量,例如bash和mksh's BASHPID
² 至少,这是传统且通常的实现。如果壳可以模仿行为,则壳可以优化叉子。

相关手册页:fork(2)execve(2)


谢谢。使用bash shebang运行bash脚本属于什么?
蒂姆(Tim)

@Tim与sh -c:这是一个子进程,碰巧恰巧是一个shell。
吉尔斯(Gillles)“所以-不要再邪恶了”

(1)“启动外部命令(sh或任何其他命令)会先调用fork系统调用,然后再执行系统调用将子进程中的Shell程序替换为另一个程序(此处为sh)。” fork首先创建一个子shell,然后用execve用外部程序替换该子shell对吗?因此,在您的两种答复中,总是创建一个子外壳吗?(2)“一个与现有外壳重复的子外壳。” 那是什么意思?
蒂姆(Tim)

(3)在中bash -c <command>,先将shell分叉,然后执行execve bash -c <command>,然后创建一个bash shell。然后,用于<command>再次运行的系统调用是否会分叉bash shell和execve <command>
蒂姆(Tim)

2
@cuonglm“子外壳”不是具有特定含义的技术术语,与“子外壳”不同。如果这是一个孩子的外壳,那么它就是一个孩子外壳,遵循英语的通常规则。
吉尔(Gilles)'所以

1

子外壳环境不需要生活在单独的进程中,只需要复制当前的执行环境即可。在ksh93这个由做virtual sub-shell不调用机制fork()。这使得ksh93在诸如之类的过时平台上非常快Win-DOS,而Win-DOS对于分叉而言则非常慢。

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

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


那么,在其他shell中ksh93,subshel​​l是子shell,对吗?
cuonglm '16

我知道今天没有其他实现虚拟子外壳的实现。
2016年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.