Selon ceci et cela , un sous-shell est démarré en utilisant des parenthèses (…)
.
( echo "Hello" )
Selon ceci , ceci et cela , un processus est bifurqué lorsque la commande est lancée avec un&
echo "Hello" &
La spécification Posix utilise le mot subshell
dans cette page mais ne le définit pas et, également, sur la même page, ne définit pas le "processus enfant" .
Les deux utilisent la fork()
fonction noyau , n'est-ce pas?
Quelle est alors la différence exacte d'appeler certaines fourches un "sous-shell" et d'autres fourches un "processus enfant".
child process
pourrait avoir un environnement distinct quemain
: comme dans( LANG=C eval 'echo "$LANG"' )
. Ce processus enfant (entre parenthèses) est-il également un sous-shell (environnement différent)?( )
est par définition un sous-shell avec son propre environnement d'exécution. Mon point est qu'il n'est pas nécessaire d'implémenter un sous-shell en tant que processus enfant (comme le souligne Stéphane dans sa réponse avec l'exemple ksh93). Il semble que le sous - shell et le processus enfant ne doivent pas être les deux résultats d'unfork()
appel; ainsi, chercher la différence entre deux types de fourches ne me semble pas le bon point de vue. C'est pourquoi j'essayais de mieux comprendre votre question.Réponses:
Dans la terminologie POSIX, un environnement de sous-shell est lié à la notion d' environnement d'exécution Shell .
Un environnement de sous-shell est un environnement d'exécution de shell distinct créé en tant que doublon de l'environnement parent. Cet environnement d'exécution comprend des choses comme les fichiers ouverts, umask, le répertoire de travail, les variables / fonctions / alias du shell ...
Les modifications apportées à cet environnement de sous-shell n'affectent pas l'environnement parent.
Traditionnellement dans le shell Bourne ou ksh88 sur lequel la spécification POSIX est basée, cela se faisait en forçant un processus enfant.
Les domaines dans lesquels POSIX requiert ou autorise l'exécution de la commande dans un environnement de sous-shell sont ceux où ksh88 a traditionnellement bifurqué un processus shell enfant.
Cela ne force cependant pas les implémentations à utiliser un processus enfant pour cela.
Un shell peut choisir d'implémenter cet environnement d'exécution séparé comme bon lui semble.
Par exemple, ksh93 le fait en enregistrant les attributs de l'environnement d'exécution parent et en les restaurant à la fin de l'environnement de sous-shell dans des contextes où le forking peut être évité (comme une optimisation car le forking est assez cher sur la plupart des systèmes).
Par exemple, dans:
POSIX a besoin
cd /foo
de s'exécuter dans un environnement séparé et de produire quelque chose comme:Il ne nécessite pas qu'il s'exécute dans un processus distinct. Par exemple, si stdout devient un tube cassé,
pwd
exécuté dans l'environnement de sous-shell pourrait très bien envoyer le SIGPIPE au seul et unique processus shell.La plupart des shells, y compris
bash
, l'implémenteront en évaluant le code à l'intérieur(...)
d'un processus enfant (pendant que le processus parent attend sa fin), mais ksh93 le fera à la place lors de l'exécution du code à l'intérieur(...)
, le tout dans le même processus:cd
, enregistrez le répertoire de travail précédent (généralement sur un descripteur de fichier ouvert avec O_CLOEXEC), enregistrez la valeur des variables OLDPWD, PWD et tout ce quicd
pourrait modifier, puis effectuez lachdir("/bar")
fchdir()
sur ce fd enregistré), et tout ce que le sous-shell peut avoir modifié.Il existe des contextes où un processus enfant ne peut pas être évité. ksh93 ne débouche pas:
var=$(subshell)
(subshell)
Mais en
{ subshell; } &
{ subshell; } | other command
C'est-à-dire les cas où les choses doivent s'exécuter dans des processus séparés pour pouvoir s'exécuter simultanément.
Les optimisations de ksh93 vont plus loin. Par exemple, en
la plupart des shells bifurquent un processus, demandent à l'enfant d'exécuter la
pwd
commande avec sa sortie standard redirigée vers un canal,pwd
écrivent le répertoire de travail actuel dans ce canal et le processus parent lit le résultat à l'autre extrémité du canal,ksh93
virtualise tout cela par aucun des deux nécessitant la fourche ni le tuyau. Une fourche et un tuyau ne seront utilisés que pour les commandes non intégrées.Notez qu'il existe des contextes autres que des sous-shell pour lesquels les shells forkent un processus enfant. Par exemple, pour exécuter une commande qui est stockée dans un exécutable séparé (et qui n'est pas un script destiné au même interpréteur de shell), un shell devrait bifurquer un processus pour exécuter cette commande, sinon il ne le serait pas capable d'exécuter plus de commandes après le retour de cette commande.
Dans:
Ce n'est pas un sous-shell, la commande sera évaluée dans l'environnement d'exécution du shell actuel, la
n
variable de l'environnement d'exécution du shell actuel sera incrémentée, mais le shell forkera un processus enfant pour exécuter cette/bin/echo
commande avec l'expansion de l'$((n += 1))
argument as .De nombreux shells implémentent une optimisation en ce sens qu'ils ne forcent pas un processus enfant pour exécuter cette commande externe s'il s'agit de la dernière commande d'un script ou d'un sous-shell (pour les sous-shells qui sont implémentés en tant que processus enfants). (
bash
mais seulement si cette commande est la seule commande du sous-shell).Cela signifie que, avec ces shells, si la dernière commande dans le sous-shell est une commande externe, le sous-shell ne provoque pas la génération d'un processus supplémentaire. Si vous comparez:
avec
il y aura le même nombre de processus créés, seulement dans le deuxième cas, le deuxième fork est fait plus tôt pour que le
a=2
soit exécuté dans un environnement de sous-shell.la source
Sous-coque
L'enveloppe enfant est également appelée sous-coque. La sous-coque peut être créée à partir du shell parent et d'un autre shell. La sous-coque peut être créée en utilisant:
1. Liste des processus
Une liste de processus est un regroupement de commandes entre parenthèses. Exemple:
Cela affichera le répertoire de travail actuel et le nombre de shell générés. REMARQUE Invoquer un sous-shell coûte cher.
2. Coprocessus
Il génère un sous-shell en mode arrière-plan et exécute une commande dans ce sous-shell.
Si vous tapez la
jobs
commandevous verrez le sommeil comme processus d'arrière-plan exécuté en arrière-plan.
Forker un processus enfant
Un processus enfant en informatique est un processus créé par un autre processus. Chaque fois qu'une commande externe est exécutée, un processus enfant est créé. Cette action est appelée fourche.
Tout
ps -f
comme la commande externe (c'est-à-dire qu'une commande externe, parfois appelée commande de système de fichiers, est un programme qui existe en dehors du shell bash.), Cela créera un processus enfant avec l'ID parent du shell bash à partir duquel il est exécuté.la source
Les deux (sous-shell et shell enfant) sont un processus distinct du shell parent (les deux sont des enfants du shell parent). Autrement dit, ils ont différents PID. Et les deux commencent par un fork (copie) du shell parent.
Un sous-shell est une copie du shell parent dans lequel les variables, fonctions, drapeaux et tout est disponible tel qu'il était dans le shell parent. Les modifications de ces valeurs n'affectent pas le parent.
Un shell enfant démarre en tant que fork mais il est réinitialisé aux valeurs par défaut du shell données par les configurations de démarrage. Il devient un processus utilisé pour exécuter du code (soit un shell, soit une commande).
Un sous-shell peut accéder aux valeurs variables:
Un shell enfant n'a pas pu (variables non exportées):
la source