Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 为什么shell命令“;{command1;command2:}&&引用;打开地下室?_Linux_Bash_Shell_Subshell - Fatal编程技术网

Linux 为什么shell命令“;{command1;command2:}&&引用;打开地下室?

Linux 为什么shell命令“;{command1;command2:}&&引用;打开地下室?,linux,bash,shell,subshell,Linux,Bash,Shell,Subshell,众所周知,在大括号之间放置命令列表会导致在当前shell上下文中执行该列表。没有创建子shell。但是当在“{}”之后使用“&”时,为什么要创建两个子shell呢?pid 1002和1003 { ./a.out } & sleep 19 使用“/a.out&”时,仅创建子shell。pid 17358 ./a.out & sleep 19 为什么?如果命令被控制运算符终止&,shell将在子shell中的后台执行该命令(或包含在{…}中的命令列表)(或异步执行)

众所周知,在大括号之间放置命令列表会导致在当前shell上下文中执行该列表。没有创建子shell。但是当在“{}”之后使用“&”时,为什么要创建两个子shell呢?pid 1002和1003

{
    ./a.out
} &

sleep 19


使用“/a.out&”时,仅创建子shell。pid 17358

./a.out &
sleep 19


为什么?

如果命令被控制运算符终止&,shell将在子shell中的后台执行该命令(或包含在
{…}
中的命令列表)(或异步执行)

shell不会等待命令完成,返回状态为0

在C程序中,它是通过执行
fork()
然后执行
execvp()
系统调用来完成的


更新:基于以下评论和更新的问题。下面是正在发生的事情

运行时:

./a.out &
{ ./a.out; } &
BASH直接在后台运行
a.out
,因为运行二进制
a.out
不需要单独的shell进程

运行时:

./a.out &
{ ./a.out; } &

BASH必须首先分叉并创建一个子shell,因为您可以在
{…}
中使用一系列命令,然后新分叉的子shell在单独的进程中运行
a.out
。因此,BASH并不是在为此创建2个子shell。只创建了一个子shell,您看到的第二个pid用于
a。out

列表的后台执行使用子shell,因为需要等待该列表的每个成员并运行下一个。在列表背景化后,父shell需要可用于新命令;它也无法管理背景列表。bash一次只能做一件事。因此,为了使背景列表起作用,它运行一个子shell

请注意,您可以否认后台列表,它将继续运行,表明子shell正在工作:

$ {
> sleep 1; sleep 2; sleep 3; sleep 4; sleep 5
> } &
$ disown
$ ps -f | grep sleep
dave     31845 31842  0 03:50 pts/1    00:00:00 sleep 3 
dave     31849 31771  0 03:50 pts/1    00:00:00 grep sleep
您甚至可以注销,子shell将继续运行列表中的进程

当您对单个命令进行后台处理时,不需要子shell,因为shell在运行该命令后不再需要执行更多的工作


在您的示例中,第二个附加的bash子流程PID 1002似乎是您正在执行的脚本。这与列表背景机制无关(至少在概念上是这样);单独文件中的任何脚本都有自己的bash进程。

但使用“/a.out&”时只创建子shell。而“{./a.out}&”则表示在子shell的子shell中执行的命令。
&
在任何命令前面将使该命令在子shell中运行a.out
int main(){sleep(100);return 0;}
您的意思是说“使用“./a.out&”时,不会创建子shell吗?只创建子shell。pid为17358。但是,“{./a.out}&”,创建了两个子shell。pid 1003和1002,戴夫,谢谢。但是我不知道为什么commond“{./a.out}&”会导致创建两个子shell?它不会;它只创建一个额外的shell(在您的示例中为PID 1003)来管理管道。在您的示例中,PID 1002似乎是一个包含“{./a.out}&”的脚本,这是它自己的shell,原因不同。使用shell(PID 1003)管理管道?你能详细解释一下吗?这就是我在回答中解释的:子shell等待每个命令完成,然后开始下一个命令。不过,我不应该说“管道”,因为命令不是通过管道一个接一个地传递的。这是一系列独立的命令。Dave,我已经弄明白了。谢谢你的帮助。