I am reading The TTY demystified. In the "Jobs and sessions" section there is an example of a user using an xterm:
$ cat
hello
hello
^Z
[1]+ Stopped cat
$ ls | sort
And there is a table listing the processes involved: xterm, bash (child of the xterm), and the three last processes (cat, ls and sort) all have the same PPID (parent process ID) -- they are all children of the same bash process.
Now, I know that pipelines in bash are executed in subshells. I have always thought that this subshell thing meant that there was an extra bash process for each subshell. My question is: shouldn't there be another two bash processes, both children of the first bash, and then ls would be a child of the first bash, and sort would be a child of the second bash? Is the table in the article simplified, or is my understanding of subshells wrong?
Programs are executed in child processes, but these are not subshells. The shell forks a child, redirects standard input/output/error as necessary, and then immediately calls execv() to execute the program.
For a very brief period the child process is still running bash, but we don't consider this a subshell because it's not doing any shell command processing -- that was all done in the original shell, and the child is just starting up the external program (as if via an explicit exec for commands like ls).
In the case of a pipeline, if any of the commands are shell built-ins, they run in a subshell. So if you do:
ls | read var
it will create two child processes. One child will run ls, the other will be a subshell executing read var.
Invoking an executable, whether directly or via a pipe, does not spawn a subshell. Only explicitly invoking it within a subshell (via (...), $(...), and so on) does so.
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