As we all know, placing a list of commands between curly braces causes the list to be executed in the current shell context. No subshell is created. But when using "&" after "{}", why two subshells are created? pid 1002 and 1003.
{
./a.out
} &
sleep 19
when using "./a.out &", only a subshell is created. pid 17358.
./a.out &
sleep 19
Why ?
Background execution of a list uses a subshell because something needs to wait for each member of that list and run the next one. After a list is backgrounded, the parent shell needs to be available for new commands; it can't manage the backgrounded list too. bash can't do more than one thing at a time. So, to make the backgrounded list work, it runs a subshell.
Note that you can disown a backgrounded list and it will keep running, showing that the subshell is doing its work:
$ {
> 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
You could even log out and the subshell would continue running processes in the list.
When you background a single command, there is no need for a subshell because there is no more work for the shell to do after it has run the command.
In your example, the second additional bash subprocess, PID 1002, appears to be a script which you're executing. That's unrelated (conceptually, at least) to the list-backgrounding mechanism; any script in a separate file has its own bash process.
If a command is terminated by the control operator &, the shell executes the command (or list of commands that are enclosed in {...}
) in the background (or asynchronously) in a subshell.
The shell does not wait for the command to finish, and the return status is 0.
In C program it is done by doing a fork()
followed by execvp()
system calls.
Update: Based on comments below and updated question. Here is what is happening.
When you run:
./a.out &
BASH directly just runs a.out
in background as running binary a.out
doesn't need a separate shell process.
When you run:
{ ./a.out; } &
BASH must first fork and create a subshell as you can have series of commands inside {...}
and then the newly forked subshell runs a.out
in a separate process. So it is not that BASH is creating 2 subshells for this. Only one subshell gets created and 2nd pid you're seeing is for a.out
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With