What is the exact difference between a “subshell” and a “child process”?












8















According to this and this, a subshell is started by using parenthesis (…).



( echo "Hello" )


According to this, this and this, a process is forked when the command is started with a &



echo "Hello" &


The Posix specification use the word subshell in this page but doesn't define it and, also, on the same page, doesn't define "child process".



Both are using the kernel fork() function, correct?



What is the exact difference then to call some forks a "sub-shell" and some other forks a "child process".










share|improve this question

























  • Not clear why you are linking POSIX Rationale: Base Definitions instead of the Base Definitions themselves: 3.93 Child Process "A new process created (by fork(), posix_spawn(), or ...) by a given process"; 3.376 Subshell "A shell execution environment, distinguished from the main or current shell execution environment". So, not instances of the same kind of thing. Is this the distinction you are looking for?

    – fra-san
    2 days ago













  • @fra-san A child process could have a distinct environment than main: Like in ( LANG=C eval 'echo "$LANG"' ). Is that child process (inside parenthesis) also a subshell (different environment)?

    – Isaac
    yesterday











  • The expression in ( ) is by definition a subshell with its own execution environment. My point is that a subshell is not required to be implemented as a child process (as Stéphane points out in his answer with the ksh93 example). It looks like subshell and child process have not to be both results of a fork() call; thus, looking for the difference between two kinds of fork doesn't seem the right point of view to me. That's why I was trying to better understand your question.

    – fra-san
    14 hours ago











  • Ah, now I see that the tldp page you linked to actually says that a subshell is a child process. In my opinion that definition is a possibly misleading simplification.

    – fra-san
    13 hours ago
















8















According to this and this, a subshell is started by using parenthesis (…).



( echo "Hello" )


According to this, this and this, a process is forked when the command is started with a &



echo "Hello" &


The Posix specification use the word subshell in this page but doesn't define it and, also, on the same page, doesn't define "child process".



Both are using the kernel fork() function, correct?



What is the exact difference then to call some forks a "sub-shell" and some other forks a "child process".










share|improve this question

























  • Not clear why you are linking POSIX Rationale: Base Definitions instead of the Base Definitions themselves: 3.93 Child Process "A new process created (by fork(), posix_spawn(), or ...) by a given process"; 3.376 Subshell "A shell execution environment, distinguished from the main or current shell execution environment". So, not instances of the same kind of thing. Is this the distinction you are looking for?

    – fra-san
    2 days ago













  • @fra-san A child process could have a distinct environment than main: Like in ( LANG=C eval 'echo "$LANG"' ). Is that child process (inside parenthesis) also a subshell (different environment)?

    – Isaac
    yesterday











  • The expression in ( ) is by definition a subshell with its own execution environment. My point is that a subshell is not required to be implemented as a child process (as Stéphane points out in his answer with the ksh93 example). It looks like subshell and child process have not to be both results of a fork() call; thus, looking for the difference between two kinds of fork doesn't seem the right point of view to me. That's why I was trying to better understand your question.

    – fra-san
    14 hours ago











  • Ah, now I see that the tldp page you linked to actually says that a subshell is a child process. In my opinion that definition is a possibly misleading simplification.

    – fra-san
    13 hours ago














8












8








8


4






According to this and this, a subshell is started by using parenthesis (…).



( echo "Hello" )


According to this, this and this, a process is forked when the command is started with a &



echo "Hello" &


The Posix specification use the word subshell in this page but doesn't define it and, also, on the same page, doesn't define "child process".



Both are using the kernel fork() function, correct?



What is the exact difference then to call some forks a "sub-shell" and some other forks a "child process".










share|improve this question
















According to this and this, a subshell is started by using parenthesis (…).



( echo "Hello" )


According to this, this and this, a process is forked when the command is started with a &



echo "Hello" &


The Posix specification use the word subshell in this page but doesn't define it and, also, on the same page, doesn't define "child process".



Both are using the kernel fork() function, correct?



What is the exact difference then to call some forks a "sub-shell" and some other forks a "child process".







bash shell subshell






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 '18 at 19:40







Isaac

















asked Jan 31 '18 at 17:12









IsaacIsaac

12k11852




12k11852













  • Not clear why you are linking POSIX Rationale: Base Definitions instead of the Base Definitions themselves: 3.93 Child Process "A new process created (by fork(), posix_spawn(), or ...) by a given process"; 3.376 Subshell "A shell execution environment, distinguished from the main or current shell execution environment". So, not instances of the same kind of thing. Is this the distinction you are looking for?

    – fra-san
    2 days ago













  • @fra-san A child process could have a distinct environment than main: Like in ( LANG=C eval 'echo "$LANG"' ). Is that child process (inside parenthesis) also a subshell (different environment)?

    – Isaac
    yesterday











  • The expression in ( ) is by definition a subshell with its own execution environment. My point is that a subshell is not required to be implemented as a child process (as Stéphane points out in his answer with the ksh93 example). It looks like subshell and child process have not to be both results of a fork() call; thus, looking for the difference between two kinds of fork doesn't seem the right point of view to me. That's why I was trying to better understand your question.

    – fra-san
    14 hours ago











  • Ah, now I see that the tldp page you linked to actually says that a subshell is a child process. In my opinion that definition is a possibly misleading simplification.

    – fra-san
    13 hours ago



















  • Not clear why you are linking POSIX Rationale: Base Definitions instead of the Base Definitions themselves: 3.93 Child Process "A new process created (by fork(), posix_spawn(), or ...) by a given process"; 3.376 Subshell "A shell execution environment, distinguished from the main or current shell execution environment". So, not instances of the same kind of thing. Is this the distinction you are looking for?

    – fra-san
    2 days ago













  • @fra-san A child process could have a distinct environment than main: Like in ( LANG=C eval 'echo "$LANG"' ). Is that child process (inside parenthesis) also a subshell (different environment)?

    – Isaac
    yesterday











  • The expression in ( ) is by definition a subshell with its own execution environment. My point is that a subshell is not required to be implemented as a child process (as Stéphane points out in his answer with the ksh93 example). It looks like subshell and child process have not to be both results of a fork() call; thus, looking for the difference between two kinds of fork doesn't seem the right point of view to me. That's why I was trying to better understand your question.

    – fra-san
    14 hours ago











  • Ah, now I see that the tldp page you linked to actually says that a subshell is a child process. In my opinion that definition is a possibly misleading simplification.

    – fra-san
    13 hours ago

















Not clear why you are linking POSIX Rationale: Base Definitions instead of the Base Definitions themselves: 3.93 Child Process "A new process created (by fork(), posix_spawn(), or ...) by a given process"; 3.376 Subshell "A shell execution environment, distinguished from the main or current shell execution environment". So, not instances of the same kind of thing. Is this the distinction you are looking for?

– fra-san
2 days ago







Not clear why you are linking POSIX Rationale: Base Definitions instead of the Base Definitions themselves: 3.93 Child Process "A new process created (by fork(), posix_spawn(), or ...) by a given process"; 3.376 Subshell "A shell execution environment, distinguished from the main or current shell execution environment". So, not instances of the same kind of thing. Is this the distinction you are looking for?

– fra-san
2 days ago















@fra-san A child process could have a distinct environment than main: Like in ( LANG=C eval 'echo "$LANG"' ). Is that child process (inside parenthesis) also a subshell (different environment)?

– Isaac
yesterday





@fra-san A child process could have a distinct environment than main: Like in ( LANG=C eval 'echo "$LANG"' ). Is that child process (inside parenthesis) also a subshell (different environment)?

– Isaac
yesterday













The expression in ( ) is by definition a subshell with its own execution environment. My point is that a subshell is not required to be implemented as a child process (as Stéphane points out in his answer with the ksh93 example). It looks like subshell and child process have not to be both results of a fork() call; thus, looking for the difference between two kinds of fork doesn't seem the right point of view to me. That's why I was trying to better understand your question.

– fra-san
14 hours ago





The expression in ( ) is by definition a subshell with its own execution environment. My point is that a subshell is not required to be implemented as a child process (as Stéphane points out in his answer with the ksh93 example). It looks like subshell and child process have not to be both results of a fork() call; thus, looking for the difference between two kinds of fork doesn't seem the right point of view to me. That's why I was trying to better understand your question.

– fra-san
14 hours ago













Ah, now I see that the tldp page you linked to actually says that a subshell is a child process. In my opinion that definition is a possibly misleading simplification.

– fra-san
13 hours ago





Ah, now I see that the tldp page you linked to actually says that a subshell is a child process. In my opinion that definition is a possibly misleading simplification.

– fra-san
13 hours ago










3 Answers
3






active

oldest

votes


















10














In the POSIX terminology, a subshell environment is linked to the notion of Shell Execution Environment.



A subshell environment is a separate shell execution environment created as a duplicate of the parent environment. That execution environment includes things like opened files, umask, working directory, shell variables/functions/aliases...



Changes to that subshell environment do not affect the parent environment.



Traditionally in the Bourne shell or ksh88 on which the POSIX specification is based, that was done by forking a child process.



The areas where POSIX requires or allows command to run in a subshell environment are those where traditionally ksh88 forked a child shell process.



It doesn't however force implementations to use a child process for that.



A shell can choose instead to implement that separate execution environment any way they like.



For instance, ksh93 does it by saving the attributes of the parent execution environment and restoring them upon termination of the subshell environment in contexts where forking can be avoided (as an optimisation as forking is quite expensive on most systems).



For instance, in:



cd /foo; pwd
(cd /bar; pwd)
pwd


POSIX does require the cd /foo to run in a separate environment and that to output something like:



/foo
/bar
/foo


It doesn't require it to run in a separate process. For instance, if stdout becomes a broken pipe, pwd run in the subshell environment could very well have the SIGPIPE sent to the one and only shell process.



Most shells including bash will implement it by evaluating the code inside (...) in a child process (while the parent process waits for its termination), but ksh93 will instead upon running the code inside (...), all in the same process:




  • remember it is in a subshell environment.

  • upon cd, save the previous working directory (typically on a file descriptor opened with O_CLOEXEC), save the value of the OLDPWD, PWD variables and anything that cd might modify and then do the chdir("/bar")

  • upon returning from the subshell, the current working directory is restored (with a fchdir() on that saved fd), and everything else that the subshell may have modified.


There are contexts where a child process can't be avoided. ksh93 doesn't fork in:




  • var=$(subshell)

  • (subshell)


But does in




  • { subshell; } &

  • { subshell; } | other command


That is, the cases where things have to run in separate processes so they can run concurrently.



ksh93 optimisations go further than that. For instance, while in



var=$(pwd)


most shells would fork a process, have the child run the pwd command with its stdout redirected to a pipe, pwd write the current working directory to that pipe, and the parent process read the result at the other end of the pipe, ksh93 virtualises all that by neither requiring the fork nor the pipe. A fork and pipe would only be used for non-builtin commands.



Note that there are contexts other that subshells for which shells fork a child process. For instance, to run a command that is stored in a separate executable (and that is not a script intended for the same shell interpreter), a shell would have to fork a process to run that command in it as otherwise it wouldn't be able to run more commands after that command returns.



In:



/bin/echo "$((n += 1))"


That is not a subshell, the command will be evaluated in the current shell execution environment, the n variable of the current shell execution environment will be incremented, but the shell will fork a child process to execute that /bin/echo command in it with the expansion of $((n += 1)) as argument.



Many shells implement an optimisation in that they don't fork a child process to run that external command if it's the last command of a script or a subshell (for those subshells that are implemented as child processes).
(bash however only does it if that command is the only command of the subshell).



What that means is that, with those shells, if the last command in the subshell is an external command, the subshell doesn't not cause an extra process to be spawned. If you compare:



a=1; /bin/echo "$a"; a=2; /bin/echo "$a"


with



a=1; /bin/echo "$a"; (a=2; /bin/echo "$a")


there will be the same number of processes created, only in the second case, the second fork is done earlier so that the a=2 is run in a subshell environment.






share|improve this answer


























  • +1, However: You link the difference to the notion of Shell Execution Environment But both start as the same environment as the parent/shell environment. That is a distinction without a difference. This doesn't answer the question and for that I have not select it.

    – Isaac
    Nov 21 '18 at 19:48



















1














Subshell



Child shell is also called subshell. Subshell can be created from parent shell and from another shell. Subshell can be created using:

1. Process List:
A process list is command grouping enclosed in parenthesis.Example



( pwd ; (echo $BASH_SUBSHELL)) 


this will print current working directory and number of spawned shell. NOTE Invoking subshell is expensive.

2. Cocprocess

It spawns a subshell in background mode and executes a command within that subshell.



coproc sleep 10


if you type jobs command



[1]+  Running                 coproc COPROC sleep 10 &


you will see sleep as background process running in background.



Forking a Child Process



A child process in computing is a process created by another process. Whenever an external command is executed, a child process is created. This action is
termed forking.



$ps -f
UID PID PPID C STIME TTY TIME CMD
umcr7 3647 3638 0 13:54 pts/0 00:00:00 bash
umcr7 3749 3647 0 13:59 pts/0 00:00:00 ps -f


As ps -f is external command (i.e. An external command, sometimes called a filesystem command, is a program that exists
outside of the bash shell. ) this will create child process with parent id of bash shell from which it is executed.






share|improve this answer































    0














    A subshell is a copy of the parent shell (which usually runs in a child process).



    A child process is a process called to run some code (either a shell, subshell or a command).





    1. A clear example of a subshell is what a shell (usually) does on a ( … ) call:




      • forks the parent shell, creating a sub-shell

      • The sub-shell executes the code inside the ( … )

      • The sub-shell returns the exit code, stdout and stderr to the parent shell.

      • The parent shell process the exit code, and the stdout and stderr strings.


      Some shells may implement the call to ( … ) (or $(…)) without a subshell (faster).



      $ seq 1000000 > file

      $ time ksh -c 'var=$(<file)'
      run : 0.462s sec

      $ time zsh -c 'var=$(<file)'
      run : 2.037s sec



    2. A child process is started (mostly) when an external command is called:



      $ ls


      Is the process in which the command gets executed.








    share|improve this answer























      Your Answer








      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "106"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f421020%2fwhat-is-the-exact-difference-between-a-subshell-and-a-child-process%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      10














      In the POSIX terminology, a subshell environment is linked to the notion of Shell Execution Environment.



      A subshell environment is a separate shell execution environment created as a duplicate of the parent environment. That execution environment includes things like opened files, umask, working directory, shell variables/functions/aliases...



      Changes to that subshell environment do not affect the parent environment.



      Traditionally in the Bourne shell or ksh88 on which the POSIX specification is based, that was done by forking a child process.



      The areas where POSIX requires or allows command to run in a subshell environment are those where traditionally ksh88 forked a child shell process.



      It doesn't however force implementations to use a child process for that.



      A shell can choose instead to implement that separate execution environment any way they like.



      For instance, ksh93 does it by saving the attributes of the parent execution environment and restoring them upon termination of the subshell environment in contexts where forking can be avoided (as an optimisation as forking is quite expensive on most systems).



      For instance, in:



      cd /foo; pwd
      (cd /bar; pwd)
      pwd


      POSIX does require the cd /foo to run in a separate environment and that to output something like:



      /foo
      /bar
      /foo


      It doesn't require it to run in a separate process. For instance, if stdout becomes a broken pipe, pwd run in the subshell environment could very well have the SIGPIPE sent to the one and only shell process.



      Most shells including bash will implement it by evaluating the code inside (...) in a child process (while the parent process waits for its termination), but ksh93 will instead upon running the code inside (...), all in the same process:




      • remember it is in a subshell environment.

      • upon cd, save the previous working directory (typically on a file descriptor opened with O_CLOEXEC), save the value of the OLDPWD, PWD variables and anything that cd might modify and then do the chdir("/bar")

      • upon returning from the subshell, the current working directory is restored (with a fchdir() on that saved fd), and everything else that the subshell may have modified.


      There are contexts where a child process can't be avoided. ksh93 doesn't fork in:




      • var=$(subshell)

      • (subshell)


      But does in




      • { subshell; } &

      • { subshell; } | other command


      That is, the cases where things have to run in separate processes so they can run concurrently.



      ksh93 optimisations go further than that. For instance, while in



      var=$(pwd)


      most shells would fork a process, have the child run the pwd command with its stdout redirected to a pipe, pwd write the current working directory to that pipe, and the parent process read the result at the other end of the pipe, ksh93 virtualises all that by neither requiring the fork nor the pipe. A fork and pipe would only be used for non-builtin commands.



      Note that there are contexts other that subshells for which shells fork a child process. For instance, to run a command that is stored in a separate executable (and that is not a script intended for the same shell interpreter), a shell would have to fork a process to run that command in it as otherwise it wouldn't be able to run more commands after that command returns.



      In:



      /bin/echo "$((n += 1))"


      That is not a subshell, the command will be evaluated in the current shell execution environment, the n variable of the current shell execution environment will be incremented, but the shell will fork a child process to execute that /bin/echo command in it with the expansion of $((n += 1)) as argument.



      Many shells implement an optimisation in that they don't fork a child process to run that external command if it's the last command of a script or a subshell (for those subshells that are implemented as child processes).
      (bash however only does it if that command is the only command of the subshell).



      What that means is that, with those shells, if the last command in the subshell is an external command, the subshell doesn't not cause an extra process to be spawned. If you compare:



      a=1; /bin/echo "$a"; a=2; /bin/echo "$a"


      with



      a=1; /bin/echo "$a"; (a=2; /bin/echo "$a")


      there will be the same number of processes created, only in the second case, the second fork is done earlier so that the a=2 is run in a subshell environment.






      share|improve this answer


























      • +1, However: You link the difference to the notion of Shell Execution Environment But both start as the same environment as the parent/shell environment. That is a distinction without a difference. This doesn't answer the question and for that I have not select it.

        – Isaac
        Nov 21 '18 at 19:48
















      10














      In the POSIX terminology, a subshell environment is linked to the notion of Shell Execution Environment.



      A subshell environment is a separate shell execution environment created as a duplicate of the parent environment. That execution environment includes things like opened files, umask, working directory, shell variables/functions/aliases...



      Changes to that subshell environment do not affect the parent environment.



      Traditionally in the Bourne shell or ksh88 on which the POSIX specification is based, that was done by forking a child process.



      The areas where POSIX requires or allows command to run in a subshell environment are those where traditionally ksh88 forked a child shell process.



      It doesn't however force implementations to use a child process for that.



      A shell can choose instead to implement that separate execution environment any way they like.



      For instance, ksh93 does it by saving the attributes of the parent execution environment and restoring them upon termination of the subshell environment in contexts where forking can be avoided (as an optimisation as forking is quite expensive on most systems).



      For instance, in:



      cd /foo; pwd
      (cd /bar; pwd)
      pwd


      POSIX does require the cd /foo to run in a separate environment and that to output something like:



      /foo
      /bar
      /foo


      It doesn't require it to run in a separate process. For instance, if stdout becomes a broken pipe, pwd run in the subshell environment could very well have the SIGPIPE sent to the one and only shell process.



      Most shells including bash will implement it by evaluating the code inside (...) in a child process (while the parent process waits for its termination), but ksh93 will instead upon running the code inside (...), all in the same process:




      • remember it is in a subshell environment.

      • upon cd, save the previous working directory (typically on a file descriptor opened with O_CLOEXEC), save the value of the OLDPWD, PWD variables and anything that cd might modify and then do the chdir("/bar")

      • upon returning from the subshell, the current working directory is restored (with a fchdir() on that saved fd), and everything else that the subshell may have modified.


      There are contexts where a child process can't be avoided. ksh93 doesn't fork in:




      • var=$(subshell)

      • (subshell)


      But does in




      • { subshell; } &

      • { subshell; } | other command


      That is, the cases where things have to run in separate processes so they can run concurrently.



      ksh93 optimisations go further than that. For instance, while in



      var=$(pwd)


      most shells would fork a process, have the child run the pwd command with its stdout redirected to a pipe, pwd write the current working directory to that pipe, and the parent process read the result at the other end of the pipe, ksh93 virtualises all that by neither requiring the fork nor the pipe. A fork and pipe would only be used for non-builtin commands.



      Note that there are contexts other that subshells for which shells fork a child process. For instance, to run a command that is stored in a separate executable (and that is not a script intended for the same shell interpreter), a shell would have to fork a process to run that command in it as otherwise it wouldn't be able to run more commands after that command returns.



      In:



      /bin/echo "$((n += 1))"


      That is not a subshell, the command will be evaluated in the current shell execution environment, the n variable of the current shell execution environment will be incremented, but the shell will fork a child process to execute that /bin/echo command in it with the expansion of $((n += 1)) as argument.



      Many shells implement an optimisation in that they don't fork a child process to run that external command if it's the last command of a script or a subshell (for those subshells that are implemented as child processes).
      (bash however only does it if that command is the only command of the subshell).



      What that means is that, with those shells, if the last command in the subshell is an external command, the subshell doesn't not cause an extra process to be spawned. If you compare:



      a=1; /bin/echo "$a"; a=2; /bin/echo "$a"


      with



      a=1; /bin/echo "$a"; (a=2; /bin/echo "$a")


      there will be the same number of processes created, only in the second case, the second fork is done earlier so that the a=2 is run in a subshell environment.






      share|improve this answer


























      • +1, However: You link the difference to the notion of Shell Execution Environment But both start as the same environment as the parent/shell environment. That is a distinction without a difference. This doesn't answer the question and for that I have not select it.

        – Isaac
        Nov 21 '18 at 19:48














      10












      10








      10







      In the POSIX terminology, a subshell environment is linked to the notion of Shell Execution Environment.



      A subshell environment is a separate shell execution environment created as a duplicate of the parent environment. That execution environment includes things like opened files, umask, working directory, shell variables/functions/aliases...



      Changes to that subshell environment do not affect the parent environment.



      Traditionally in the Bourne shell or ksh88 on which the POSIX specification is based, that was done by forking a child process.



      The areas where POSIX requires or allows command to run in a subshell environment are those where traditionally ksh88 forked a child shell process.



      It doesn't however force implementations to use a child process for that.



      A shell can choose instead to implement that separate execution environment any way they like.



      For instance, ksh93 does it by saving the attributes of the parent execution environment and restoring them upon termination of the subshell environment in contexts where forking can be avoided (as an optimisation as forking is quite expensive on most systems).



      For instance, in:



      cd /foo; pwd
      (cd /bar; pwd)
      pwd


      POSIX does require the cd /foo to run in a separate environment and that to output something like:



      /foo
      /bar
      /foo


      It doesn't require it to run in a separate process. For instance, if stdout becomes a broken pipe, pwd run in the subshell environment could very well have the SIGPIPE sent to the one and only shell process.



      Most shells including bash will implement it by evaluating the code inside (...) in a child process (while the parent process waits for its termination), but ksh93 will instead upon running the code inside (...), all in the same process:




      • remember it is in a subshell environment.

      • upon cd, save the previous working directory (typically on a file descriptor opened with O_CLOEXEC), save the value of the OLDPWD, PWD variables and anything that cd might modify and then do the chdir("/bar")

      • upon returning from the subshell, the current working directory is restored (with a fchdir() on that saved fd), and everything else that the subshell may have modified.


      There are contexts where a child process can't be avoided. ksh93 doesn't fork in:




      • var=$(subshell)

      • (subshell)


      But does in




      • { subshell; } &

      • { subshell; } | other command


      That is, the cases where things have to run in separate processes so they can run concurrently.



      ksh93 optimisations go further than that. For instance, while in



      var=$(pwd)


      most shells would fork a process, have the child run the pwd command with its stdout redirected to a pipe, pwd write the current working directory to that pipe, and the parent process read the result at the other end of the pipe, ksh93 virtualises all that by neither requiring the fork nor the pipe. A fork and pipe would only be used for non-builtin commands.



      Note that there are contexts other that subshells for which shells fork a child process. For instance, to run a command that is stored in a separate executable (and that is not a script intended for the same shell interpreter), a shell would have to fork a process to run that command in it as otherwise it wouldn't be able to run more commands after that command returns.



      In:



      /bin/echo "$((n += 1))"


      That is not a subshell, the command will be evaluated in the current shell execution environment, the n variable of the current shell execution environment will be incremented, but the shell will fork a child process to execute that /bin/echo command in it with the expansion of $((n += 1)) as argument.



      Many shells implement an optimisation in that they don't fork a child process to run that external command if it's the last command of a script or a subshell (for those subshells that are implemented as child processes).
      (bash however only does it if that command is the only command of the subshell).



      What that means is that, with those shells, if the last command in the subshell is an external command, the subshell doesn't not cause an extra process to be spawned. If you compare:



      a=1; /bin/echo "$a"; a=2; /bin/echo "$a"


      with



      a=1; /bin/echo "$a"; (a=2; /bin/echo "$a")


      there will be the same number of processes created, only in the second case, the second fork is done earlier so that the a=2 is run in a subshell environment.






      share|improve this answer















      In the POSIX terminology, a subshell environment is linked to the notion of Shell Execution Environment.



      A subshell environment is a separate shell execution environment created as a duplicate of the parent environment. That execution environment includes things like opened files, umask, working directory, shell variables/functions/aliases...



      Changes to that subshell environment do not affect the parent environment.



      Traditionally in the Bourne shell or ksh88 on which the POSIX specification is based, that was done by forking a child process.



      The areas where POSIX requires or allows command to run in a subshell environment are those where traditionally ksh88 forked a child shell process.



      It doesn't however force implementations to use a child process for that.



      A shell can choose instead to implement that separate execution environment any way they like.



      For instance, ksh93 does it by saving the attributes of the parent execution environment and restoring them upon termination of the subshell environment in contexts where forking can be avoided (as an optimisation as forking is quite expensive on most systems).



      For instance, in:



      cd /foo; pwd
      (cd /bar; pwd)
      pwd


      POSIX does require the cd /foo to run in a separate environment and that to output something like:



      /foo
      /bar
      /foo


      It doesn't require it to run in a separate process. For instance, if stdout becomes a broken pipe, pwd run in the subshell environment could very well have the SIGPIPE sent to the one and only shell process.



      Most shells including bash will implement it by evaluating the code inside (...) in a child process (while the parent process waits for its termination), but ksh93 will instead upon running the code inside (...), all in the same process:




      • remember it is in a subshell environment.

      • upon cd, save the previous working directory (typically on a file descriptor opened with O_CLOEXEC), save the value of the OLDPWD, PWD variables and anything that cd might modify and then do the chdir("/bar")

      • upon returning from the subshell, the current working directory is restored (with a fchdir() on that saved fd), and everything else that the subshell may have modified.


      There are contexts where a child process can't be avoided. ksh93 doesn't fork in:




      • var=$(subshell)

      • (subshell)


      But does in




      • { subshell; } &

      • { subshell; } | other command


      That is, the cases where things have to run in separate processes so they can run concurrently.



      ksh93 optimisations go further than that. For instance, while in



      var=$(pwd)


      most shells would fork a process, have the child run the pwd command with its stdout redirected to a pipe, pwd write the current working directory to that pipe, and the parent process read the result at the other end of the pipe, ksh93 virtualises all that by neither requiring the fork nor the pipe. A fork and pipe would only be used for non-builtin commands.



      Note that there are contexts other that subshells for which shells fork a child process. For instance, to run a command that is stored in a separate executable (and that is not a script intended for the same shell interpreter), a shell would have to fork a process to run that command in it as otherwise it wouldn't be able to run more commands after that command returns.



      In:



      /bin/echo "$((n += 1))"


      That is not a subshell, the command will be evaluated in the current shell execution environment, the n variable of the current shell execution environment will be incremented, but the shell will fork a child process to execute that /bin/echo command in it with the expansion of $((n += 1)) as argument.



      Many shells implement an optimisation in that they don't fork a child process to run that external command if it's the last command of a script or a subshell (for those subshells that are implemented as child processes).
      (bash however only does it if that command is the only command of the subshell).



      What that means is that, with those shells, if the last command in the subshell is an external command, the subshell doesn't not cause an extra process to be spawned. If you compare:



      a=1; /bin/echo "$a"; a=2; /bin/echo "$a"


      with



      a=1; /bin/echo "$a"; (a=2; /bin/echo "$a")


      there will be the same number of processes created, only in the second case, the second fork is done earlier so that the a=2 is run in a subshell environment.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Jan 31 '18 at 20:05

























      answered Jan 31 '18 at 17:42









      Stéphane ChazelasStéphane Chazelas

      308k57582940




      308k57582940













      • +1, However: You link the difference to the notion of Shell Execution Environment But both start as the same environment as the parent/shell environment. That is a distinction without a difference. This doesn't answer the question and for that I have not select it.

        – Isaac
        Nov 21 '18 at 19:48



















      • +1, However: You link the difference to the notion of Shell Execution Environment But both start as the same environment as the parent/shell environment. That is a distinction without a difference. This doesn't answer the question and for that I have not select it.

        – Isaac
        Nov 21 '18 at 19:48

















      +1, However: You link the difference to the notion of Shell Execution Environment But both start as the same environment as the parent/shell environment. That is a distinction without a difference. This doesn't answer the question and for that I have not select it.

      – Isaac
      Nov 21 '18 at 19:48





      +1, However: You link the difference to the notion of Shell Execution Environment But both start as the same environment as the parent/shell environment. That is a distinction without a difference. This doesn't answer the question and for that I have not select it.

      – Isaac
      Nov 21 '18 at 19:48













      1














      Subshell



      Child shell is also called subshell. Subshell can be created from parent shell and from another shell. Subshell can be created using:

      1. Process List:
      A process list is command grouping enclosed in parenthesis.Example



      ( pwd ; (echo $BASH_SUBSHELL)) 


      this will print current working directory and number of spawned shell. NOTE Invoking subshell is expensive.

      2. Cocprocess

      It spawns a subshell in background mode and executes a command within that subshell.



      coproc sleep 10


      if you type jobs command



      [1]+  Running                 coproc COPROC sleep 10 &


      you will see sleep as background process running in background.



      Forking a Child Process



      A child process in computing is a process created by another process. Whenever an external command is executed, a child process is created. This action is
      termed forking.



      $ps -f
      UID PID PPID C STIME TTY TIME CMD
      umcr7 3647 3638 0 13:54 pts/0 00:00:00 bash
      umcr7 3749 3647 0 13:59 pts/0 00:00:00 ps -f


      As ps -f is external command (i.e. An external command, sometimes called a filesystem command, is a program that exists
      outside of the bash shell. ) this will create child process with parent id of bash shell from which it is executed.






      share|improve this answer




























        1














        Subshell



        Child shell is also called subshell. Subshell can be created from parent shell and from another shell. Subshell can be created using:

        1. Process List:
        A process list is command grouping enclosed in parenthesis.Example



        ( pwd ; (echo $BASH_SUBSHELL)) 


        this will print current working directory and number of spawned shell. NOTE Invoking subshell is expensive.

        2. Cocprocess

        It spawns a subshell in background mode and executes a command within that subshell.



        coproc sleep 10


        if you type jobs command



        [1]+  Running                 coproc COPROC sleep 10 &


        you will see sleep as background process running in background.



        Forking a Child Process



        A child process in computing is a process created by another process. Whenever an external command is executed, a child process is created. This action is
        termed forking.



        $ps -f
        UID PID PPID C STIME TTY TIME CMD
        umcr7 3647 3638 0 13:54 pts/0 00:00:00 bash
        umcr7 3749 3647 0 13:59 pts/0 00:00:00 ps -f


        As ps -f is external command (i.e. An external command, sometimes called a filesystem command, is a program that exists
        outside of the bash shell. ) this will create child process with parent id of bash shell from which it is executed.






        share|improve this answer


























          1












          1








          1







          Subshell



          Child shell is also called subshell. Subshell can be created from parent shell and from another shell. Subshell can be created using:

          1. Process List:
          A process list is command grouping enclosed in parenthesis.Example



          ( pwd ; (echo $BASH_SUBSHELL)) 


          this will print current working directory and number of spawned shell. NOTE Invoking subshell is expensive.

          2. Cocprocess

          It spawns a subshell in background mode and executes a command within that subshell.



          coproc sleep 10


          if you type jobs command



          [1]+  Running                 coproc COPROC sleep 10 &


          you will see sleep as background process running in background.



          Forking a Child Process



          A child process in computing is a process created by another process. Whenever an external command is executed, a child process is created. This action is
          termed forking.



          $ps -f
          UID PID PPID C STIME TTY TIME CMD
          umcr7 3647 3638 0 13:54 pts/0 00:00:00 bash
          umcr7 3749 3647 0 13:59 pts/0 00:00:00 ps -f


          As ps -f is external command (i.e. An external command, sometimes called a filesystem command, is a program that exists
          outside of the bash shell. ) this will create child process with parent id of bash shell from which it is executed.






          share|improve this answer













          Subshell



          Child shell is also called subshell. Subshell can be created from parent shell and from another shell. Subshell can be created using:

          1. Process List:
          A process list is command grouping enclosed in parenthesis.Example



          ( pwd ; (echo $BASH_SUBSHELL)) 


          this will print current working directory and number of spawned shell. NOTE Invoking subshell is expensive.

          2. Cocprocess

          It spawns a subshell in background mode and executes a command within that subshell.



          coproc sleep 10


          if you type jobs command



          [1]+  Running                 coproc COPROC sleep 10 &


          you will see sleep as background process running in background.



          Forking a Child Process



          A child process in computing is a process created by another process. Whenever an external command is executed, a child process is created. This action is
          termed forking.



          $ps -f
          UID PID PPID C STIME TTY TIME CMD
          umcr7 3647 3638 0 13:54 pts/0 00:00:00 bash
          umcr7 3749 3647 0 13:59 pts/0 00:00:00 ps -f


          As ps -f is external command (i.e. An external command, sometimes called a filesystem command, is a program that exists
          outside of the bash shell. ) this will create child process with parent id of bash shell from which it is executed.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 21 '18 at 9:34









          Muhammad Umar AmanatMuhammad Umar Amanat

          112




          112























              0














              A subshell is a copy of the parent shell (which usually runs in a child process).



              A child process is a process called to run some code (either a shell, subshell or a command).





              1. A clear example of a subshell is what a shell (usually) does on a ( … ) call:




                • forks the parent shell, creating a sub-shell

                • The sub-shell executes the code inside the ( … )

                • The sub-shell returns the exit code, stdout and stderr to the parent shell.

                • The parent shell process the exit code, and the stdout and stderr strings.


                Some shells may implement the call to ( … ) (or $(…)) without a subshell (faster).



                $ seq 1000000 > file

                $ time ksh -c 'var=$(<file)'
                run : 0.462s sec

                $ time zsh -c 'var=$(<file)'
                run : 2.037s sec



              2. A child process is started (mostly) when an external command is called:



                $ ls


                Is the process in which the command gets executed.








              share|improve this answer




























                0














                A subshell is a copy of the parent shell (which usually runs in a child process).



                A child process is a process called to run some code (either a shell, subshell or a command).





                1. A clear example of a subshell is what a shell (usually) does on a ( … ) call:




                  • forks the parent shell, creating a sub-shell

                  • The sub-shell executes the code inside the ( … )

                  • The sub-shell returns the exit code, stdout and stderr to the parent shell.

                  • The parent shell process the exit code, and the stdout and stderr strings.


                  Some shells may implement the call to ( … ) (or $(…)) without a subshell (faster).



                  $ seq 1000000 > file

                  $ time ksh -c 'var=$(<file)'
                  run : 0.462s sec

                  $ time zsh -c 'var=$(<file)'
                  run : 2.037s sec



                2. A child process is started (mostly) when an external command is called:



                  $ ls


                  Is the process in which the command gets executed.








                share|improve this answer


























                  0












                  0








                  0







                  A subshell is a copy of the parent shell (which usually runs in a child process).



                  A child process is a process called to run some code (either a shell, subshell or a command).





                  1. A clear example of a subshell is what a shell (usually) does on a ( … ) call:




                    • forks the parent shell, creating a sub-shell

                    • The sub-shell executes the code inside the ( … )

                    • The sub-shell returns the exit code, stdout and stderr to the parent shell.

                    • The parent shell process the exit code, and the stdout and stderr strings.


                    Some shells may implement the call to ( … ) (or $(…)) without a subshell (faster).



                    $ seq 1000000 > file

                    $ time ksh -c 'var=$(<file)'
                    run : 0.462s sec

                    $ time zsh -c 'var=$(<file)'
                    run : 2.037s sec



                  2. A child process is started (mostly) when an external command is called:



                    $ ls


                    Is the process in which the command gets executed.








                  share|improve this answer













                  A subshell is a copy of the parent shell (which usually runs in a child process).



                  A child process is a process called to run some code (either a shell, subshell or a command).





                  1. A clear example of a subshell is what a shell (usually) does on a ( … ) call:




                    • forks the parent shell, creating a sub-shell

                    • The sub-shell executes the code inside the ( … )

                    • The sub-shell returns the exit code, stdout and stderr to the parent shell.

                    • The parent shell process the exit code, and the stdout and stderr strings.


                    Some shells may implement the call to ( … ) (or $(…)) without a subshell (faster).



                    $ seq 1000000 > file

                    $ time ksh -c 'var=$(<file)'
                    run : 0.462s sec

                    $ time zsh -c 'var=$(<file)'
                    run : 2.037s sec



                  2. A child process is started (mostly) when an external command is called:



                    $ ls


                    Is the process in which the command gets executed.









                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered 12 mins ago









                  IsaacIsaac

                  12k11852




                  12k11852






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Unix & Linux Stack Exchange!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f421020%2fwhat-is-the-exact-difference-between-a-subshell-and-a-child-process%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Loup dans la culture

                      How to solve the problem of ntp “Unable to contact time server” from KDE?

                      ASUS Zenbook UX433/UX333 — Configure Touchpad-embedded numpad on Linux