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

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
5
down vote

favorite
1












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



( echo "Hello" )


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



echo "Hello" &


But aren't both the (…) and the & using the kernel fork() function anyway?

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







share|improve this question


























    up vote
    5
    down vote

    favorite
    1












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



    ( echo "Hello" )


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



    echo "Hello" &


    But aren't both the (…) and the & using the kernel fork() function anyway?

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







    share|improve this question
























      up vote
      5
      down vote

      favorite
      1









      up vote
      5
      down vote

      favorite
      1






      1





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



      ( echo "Hello" )


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



      echo "Hello" &


      But aren't both the (…) and the & using the kernel fork() function anyway?

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







      share|improve this question














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



      ( echo "Hello" )


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



      echo "Hello" &


      But aren't both the (…) and the & using the kernel fork() function anyway?

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









      share|improve this question













      share|improve this question




      share|improve this question








      edited Aug 15 at 7:51









      codeforester

      336314




      336314










      asked Jan 31 at 17:12









      Isaac

      6,6371734




      6,6371734




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          9
          down vote













          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






















          • This expand and detail what ksh does, thanks. But what is the general rule for most shells that makes a fork being called a subshell (or not).
            – Isaac
            Jan 31 at 18:00










          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',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          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-forking-a-child-process%23new-answer', 'question_page');

          );

          Post as a guest






























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          9
          down vote













          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






















          • This expand and detail what ksh does, thanks. But what is the general rule for most shells that makes a fork being called a subshell (or not).
            – Isaac
            Jan 31 at 18:00














          up vote
          9
          down vote













          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






















          • This expand and detail what ksh does, thanks. But what is the general rule for most shells that makes a fork being called a subshell (or not).
            – Isaac
            Jan 31 at 18:00












          up vote
          9
          down vote










          up vote
          9
          down vote









          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 at 20:05

























          answered Jan 31 at 17:42









          Stéphane Chazelas

          281k53516847




          281k53516847











          • This expand and detail what ksh does, thanks. But what is the general rule for most shells that makes a fork being called a subshell (or not).
            – Isaac
            Jan 31 at 18:00
















          • This expand and detail what ksh does, thanks. But what is the general rule for most shells that makes a fork being called a subshell (or not).
            – Isaac
            Jan 31 at 18:00















          This expand and detail what ksh does, thanks. But what is the general rule for most shells that makes a fork being called a subshell (or not).
          – Isaac
          Jan 31 at 18:00




          This expand and detail what ksh does, thanks. But what is the general rule for most shells that makes a fork being called a subshell (or not).
          – Isaac
          Jan 31 at 18:00












           

          draft saved


          draft discarded


























           


          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-forking-a-child-process%23new-answer', 'question_page');

          );

          Post as a guest













































































          Popular posts from this blog

          How to check contact read email or not when send email to Individual?

          Displaying single band from multi-band raster using QGIS

          How many registers does an x86_64 CPU actually have?