web-dev-qa-db-fra.com

Quelle est la différence exacte entre un "sous-vase" et un "processus enfant"?

Selon - Ceci et ceci , un sous -c. est démarré à l'aide d'une parenthèse (…).

( echo "Hello" )

Selon ---- (this , this et this , un processus est fourchu lorsque la commande est démarrée avec un &

echo "Hello" &

L'utilisation de la spécification POSIX le mot subshell dans cette page mais ne le définit pas et, aussi, sur la même page, ne définit pas le "processus enfant" .

Les deux utilisent le noyau fork() fonction, correct?

Quelle est la différence exacte alors d'appeler quelques fourches une "sous-shell" et d'autres fourches un "processus enfant".

16
Isaac

Les deux (Subshell and Child Shell) sont un processus séparé que la coque mère (les deux sont les enfants de la coque mère). C'est-à-dire qu'ils ont des pids différents. Et les deux commencent par une fourchette (copie) de la coque mère.

Un sous-groupe est une copie de la coque mère dans laquelle les variables, les fonctions, les drapeaux et tout est disponible car il s'agissait de la coquille mère. Les modifications de telles valeurs n'ont aucune incidence sur le parent.

Un shell enfant commence comme une fourchette, mais elle est réinitialisée aux valeurs de coquille par défaut données par les configurations de démarrage. Il devient un processus utilisé pour exécuter du code (une coquille ou une commande).

Un sous-(-shell pourrait accéder à des valeurs variables:

$ x=123; ( echo "$x")
123

Une coquille enfant ne pouvait pas (variables non exportées):

$ x=234; sh -c 'echo "x=$x"'
x=
0
Isaac

Dans la terminologie POSIX, un environnement de sous -shell est lié à la notion de --- (environnement d'exécution de shell .

Un environnement de sous-(-shell est un environnement d'exécution de shell distinct créé comme duplicata de l'environnement parent. Cet environnement d'exécution comprend des éléments tels que des fichiers ouverts, une montagne, un répertoire de travail, des variables de shell/fonctions/alias ...

Les modifications apportées à cet environnement Subshell n'affectent pas l'environnement des parents.

Traditionnellement dans la coquille de Bourne ou KSH88 sur lequel la spécification POSIX est basée, cela a été fait en faisant forger un processus d'enfant.

Les zones où POSIX nécessite ou permet à la commande de courir dans un environnement de sous-espacement sont celles où la chaîne traditionnelle KSH88 a forcé un processus d'enregistrement d'enfants.

Il ne force pas cependant les implémentations à utiliser un processus d'enfant pour cela.

Une coquille peut choisir de mettre en œuvre cet environnement d'exécution séparé de toute façon.

Par exemple, KSH93 le fait en sauvegarde les attributs de l'environnement d'exécution des parents et en les restauré lors de la résiliation de l'environnement Subshell dans des contextes où le fourche peut être évité (comme une optimisation que le fourche est assez coûteux sur la plupart des systèmes).

Par exemple, dans:

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

POSIX exige que le cd /foo fonctionne dans un environnement distinct et que pour produire quelque chose comme:

/foo
/bar
/foo

Il n'exige pas qu'il fonctionne dans un processus séparé. Par exemple, si STDOUT devient un tuyau cassé, pwd _ exécuté dans l'environnement sous-roulant pourrait très bien avoir le sigpipe envoyé au processus d'une et unique.

La plupart des coquilles comprenant bash _ _ _ _ _ _ _ _ la mettra en œuvre en évaluant le code à l'intérieur (...) dans un processus enfant (tandis que le processus parent attend sa résiliation), mais KSH93 va plutôt exécuter le code à l'intérieur (...), tout dans le même processus:

  • n'oubliez pas que c'est dans un environnement sous-vasque.
  • sur 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 OLDPWD, des variables PWD et tout ce que cd peut modifier, puis faire le chdir("/bar")
  • en retour du sous-groupe, le répertoire de travail actuel est restauré (avec une fchdir() sur la FD sauvegardée) et tout ce que le sous-épais peut avoir modifié.

Il existe des contextes où un processus enfant ne peut être évité. ksh93 ne pas fourchette dans:

  • var=$(subshell)
  • (subshell)

Mais fait dans

  • { subshell; } &
  • { subshell; } | other command

C'est-à-dire que les cas où les choses doivent courir dans des processus distincts afin qu'ils puissent courir simultanément.

ksh93 optimisations aller plus loin que cela. Par exemple, alors que dans

var=$(pwd)

la plupart des coquillages produiraient un processus, les enfants gèrent la commande pwd avec son stdout redirigé vers un tuyau, pwd Écrivez le répertoire de travail actuel sur ce tuyau et le processus parent lue le résultat L'autre extrémité du tuyau, ksh93 virtualise tout ce qui n'exigeant ni la fourche ni le tuyau. Une fourchette et une tuyau ne seraient utilisées que pour les commandes non intégrées.

Notez qu'il existe des contextes d'autres sous-rattrapés pour lesquels des coquillages fourragent un processus d'enfant. Par exemple, pour exécuter une commande stockée dans un exécutable séparé (et ce n'est pas un script destiné au même interpréteur de coque), une coque devrait avoir à fourche un processus pour exécuter cette commande en cela comme ça ne serait pas capable d'exécuter plus de commandes après cette commande renvoie.

Dans:

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

Ce n'est pas un sous-vase, la commande sera évaluée dans l'environnement d'exécution de shell actuel, la variable n de l'environnement d'exécution de shell actuel sera incrémentée, mais la coque fourrette un processus enfant pour exécuter cette commande /bin/echo dans avec l'expansion de $((n += 1)) comme argument.

De nombreux coquillages mettent en œuvre une optimisation en ce sens qu'ils ne font pas de pourcentage de 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). (bash Cependant, si cette commande est la seule commande du sous-groupe).

Ce que cela signifie, c'est que, avec ces coquilles, si la dernière commande du sous-groupe est une commande externe, le sous-groupe ne provoque pas de processus supplémentaire d'être engendré. Si vous comparez:

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

avec

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

il y aura le même nombre de processus créés, uniquement dans le second cas, la deuxième fourche est effectuée plus tôt afin que le a=2 soit exécuté dans un environnement de sous-espacement.

15
Stéphane Chazelas

Un sous-groupe est une copie de la coque mère (qui fonctionne généralement dans un processus enfant).

Un processus enfant est un processus appelé à exécuter du code (une coquille, un sous-(-shell ou une commande).

  1. Un exemple clair d'un sous-groupe est ce qu'une coquille (généralement) sur un ( … ) Appeler:

    • fourchettes la coque mère, créant une sous-coquille
    • La sous-shell exécute le code à l'intérieur du ( … )
    • La sous-shell renvoie le code de sortie, STDOUT et STDERR à la coque mère.
    • La coque mère traite le code de sortie et les chaînes STDOUT et STDERR.

    Certaines obus peuvent mettre en œuvre l'appel à ( … ) (Ou $(…)) sans sous-groupe (plus rapide).

    $ seq 1000000 > file
    
    $ time ksh -c 'var=$(<file)'
    run    : 0.462s sec
    
    $ time zsh -c 'var=$(<file)'
    run    : 2.037s sec
    
  2. Un processus enfant est lancé (principalement) lorsqu'une commande externe est appelée:

    $ ls
    

    Est le processus dans lequel la commande est exécutée.

2
Isaac

Submerger

Enfant Shell est également appelé Subshell. Subshell peut être créé à partir d'une coque mère et d'une autre coquille. Subshell peut être créé en utilisant:

1. Liste de processus

Une liste de processus est le groupe de commandes enfermé entre parenthèses. Exemple:

( pwd ; (echo $BASH_SUBSHELL)) 

Cela imprimera le répertoire de travail actuel et le nombre de shell engendrés. [~ # ~] note [~ # ~ ~] Invoquant Subshell est cher.

2. Coprocess

Il reproche un sous-vase en mode arrière-plan et exécute une commande dans ce sous-groupe.

coproc sleep 10

Si vous tapez jobs commande

[1]+  Running                 coproc COPROC sleep 10 &

vous verrez dormir comme processus d'arrière-plan en arrière-plan.

Forking un processus d'enfant

Un processus d'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 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

Comme ps -f est la commande externe (c'est-à-dire une commande externe, parfois appelée commande de fichier de fichiers, est un programme qui existe à l'extérieur de la coque Bash.) Cela créera un processus enfant avec un identifiant parent de coque Bash à partir duquel il est exécuté.

1