Según esto y esto , se inicia una subshell utilizando paréntesis (…)
.
( echo "Hello" )
De acuerdo con esto , esto y esto , un proceso se bifurca cuando el comando se inicia con un&
echo "Hello" &
La especificación Posix usa la palabra subshell
en esta página pero no la define y, también, en la misma página, no define "proceso hijo" .
Ambos están utilizando la fork()
función del núcleo , ¿correcto?
¿Cuál es la diferencia exacta entonces llamar a algunos tenedores un "sub-shell" y otros tenedores un "proceso hijo"?
child process
podría tener un entorno distinto quemain
: Me gusta en( LANG=C eval 'echo "$LANG"' )
. ¿Es ese proceso hijo (dentro de paréntesis) también una subshell (entorno diferente)?( )
es, por definición, una subshell con su propio entorno de ejecución. Mi punto es que no es necesario implementar una subshell como un proceso secundario (como Stéphane señala en su respuesta con el ejemplo ksh93). Parece que subnivel y proceso hijo no tienen que ser los dos resultados de unafork()
llamada; Por lo tanto, buscar la diferencia entre dos tipos de tenedor no me parece el punto de vista correcto. Es por eso que estaba tratando de entender mejor tu pregunta.Respuestas:
En la terminología POSIX, un entorno de subshell está vinculado a la noción de Entorno de ejecución de Shell .
Un entorno de subshell es un entorno de ejecución de shell separado creado como un duplicado del entorno principal. Ese entorno de ejecución incluye cosas como archivos abiertos, umask, directorio de trabajo, variables de shell / funciones / alias ...
Los cambios en ese entorno de subshell no afectan al entorno principal.
Tradicionalmente en el shell Bourne o ksh88 en el que se basa la especificación POSIX, eso se hizo bifurcando un proceso hijo.
Las áreas donde POSIX requiere o permite que el comando se ejecute en un entorno de subshell son aquellas donde tradicionalmente ksh88 bifurcó un proceso de shell hijo.
Sin embargo, no obliga a las implementaciones a usar un proceso hijo para eso.
Un shell puede elegir implementar ese entorno de ejecución separado de la forma que desee.
Por ejemplo, ksh93 lo hace guardando los atributos del entorno de ejecución principal y restaurándolos al terminar el entorno de subshell en contextos donde se puede evitar la bifurcación (ya que la optimización es bastante costosa en la mayoría de los sistemas).
Por ejemplo, en:
POSIX requiere
cd /foo
que se ejecute en un entorno separado y que genere algo como:No requiere que se ejecute en un proceso separado. Por ejemplo, si stdout se convierte en una tubería rota, la
pwd
ejecución en el entorno de subshell podría muy bien enviar el SIGPIPE al único proceso de shell.La mayoría de los shells incluidos
bash
lo implementarán evaluando el código dentro(...)
de un proceso secundario (mientras que el proceso principal espera su finalización), pero ksh93 lo hará al ejecutar el código dentro(...)
, todo en el mismo proceso:cd
, guarde el directorio de trabajo anterior (generalmente en un descriptor de archivo abierto con O_CLOEXEC), guarde el valor de las variables OLDPWD, PWD y cualquier cosa quecd
pueda modificar y luego realice elchdir("/bar")
fchdir()
fd guardado) y todo lo demás que la subshell puede haber modificado.Hay contextos en los que no se puede evitar un proceso hijo. ksh93 no se bifurca:
var=$(subshell)
(subshell)
Pero lo hace en
{ subshell; } &
{ subshell; } | other command
Es decir, los casos en que las cosas tienen que ejecutarse en procesos separados para que puedan ejecutarse simultáneamente.
Las optimizaciones de ksh93 van más allá de eso. Por ejemplo, mientras que en
la mayoría de los shells bifurcan un proceso, hacen que el niño ejecute el
pwd
comando con su stdout redirigido a una tubería,pwd
escribe el directorio de trabajo actual en esa tubería, y el proceso padre lee el resultado en el otro extremo de la tubería,ksh93
virtualiza todo eso de ninguna manera requiriendo la horquilla ni la tubería. Una bifurcación y una tubería solo se usarían para comandos no integrados.Tenga en cuenta que hay otros contextos que subcapas para los cuales las bifurcaciones bifurcan un proceso secundario. Por ejemplo, para ejecutar un comando que se almacena en un ejecutable separado (y que no es un script destinado al mismo intérprete de shell), un shell tendría que bifurcar un proceso para ejecutar ese comando en él, de lo contrario no sería capaz de ejecutar más comandos después de que ese comando regrese.
En:
Eso no es un subshell, el comando se evaluará en el entorno de ejecución de shell actual, la
n
variable del entorno de ejecución de shell actual se incrementará, pero el shell bifurcará un proceso secundario para ejecutar ese/bin/echo
comando en él con la expansión de$((n += 1))
como argumento .Muchos shells implementan una optimización en el sentido de que no bifurcan un proceso secundario para ejecutar ese comando externo si es el último comando de un script o un subshell (para aquellos subshell que se implementan como procesos secundarios). (
bash
sin embargo, solo lo hace si ese comando es el único comando de la subshell).Lo que eso significa es que, con esos shells, si el último comando en el subshell es un comando externo, el subshell no hace que se genere un proceso adicional. Si comparas:
con
habrá la misma cantidad de procesos creados, solo en el segundo caso, la segunda bifurcación se realiza antes para que
a=2
se ejecute en un entorno de subshell.fuente
Subshell
El shell secundario también se llama subshell. El subshell se puede crear desde el shell principal y desde otro shell. Subshell se puede crear usando:
1. Lista de procesos
Una lista de procesos es agrupación de comandos entre paréntesis. Ejemplo:
Esto imprimirá el directorio de trabajo actual y el número de shell generado. NOTA Invocar subshell es costoso.
2. Coproceso
Genera una subshell en modo de fondo y ejecuta un comando dentro de esa subshell.
Si escribe
jobs
comandoverá dormir como proceso en segundo plano ejecutándose en segundo plano.
Bifurcando un proceso hijo
Un proceso hijo en informática es un proceso creado por otro proceso. Cada vez que se ejecuta un comando externo, se crea un proceso secundario. Esta acción se denomina bifurcación.
Al igual
ps -f
que un comando externo (es decir, un comando externo, a veces llamado comando del sistema de archivos, es un programa que existe fuera del bash shell). Esto creará un proceso secundario con la identificación principal del bash shell desde el cual se ejecuta.fuente
Ambos (subshell y shell hijo) son un proceso separado del shell padre (ambos son hijos del shell padre). Es decir, tienen diferentes PID. Y ambos comienzan con una bifurcación (copia) del shell principal.
Un subshell es una copia del shell principal en el que las variables, funciones, indicadores y todo está disponible como estaba en el shell principal. Las modificaciones de tales valores no afectan al padre.
Un shell hijo comienza como una bifurcación, pero se restablece a los valores predeterminados del shell dados por las configuraciones de inicio. Se convierte en un proceso utilizado para ejecutar algún código (ya sea un shell o un comando).
Una subshell podría acceder a valores variables:
Un shell hijo no pudo (variables no exportadas):
fuente