Deesteenlace Recibo lo siguiente sobre el comando incorporado exec bash:
Si se proporciona el comando,reemplaza el caparazónsin crear un nuevo proceso.
¿Cómo reemplaza exactamente el caparazón (es decir, cómo funciona internamente)? ¿La exec*()
llamada al sistema funciona igual?
Respuesta1
Sí, la exec
función integrada finalmente utiliza una de la exec*()
familia de llamadas al sistema. También lo hace la ejecución normal de comandos. Es solo que cuando usas exec
, no usa la fork()
llamada al sistema primero para crear un nuevo proceso, y el resultado es que el nuevo comando reemplaza el shell.
Respuesta2
Hice una strace
en una bash
instancia en ejecución. Luego invoqué el comando exec sleep 100
. Ahora mira lo que pasó:
access("/bin/sleep", X_OK) = 0
...
execve("/bin/sleep", ["sleep", "100"], [/* 14 vars */]) = 0
...
nanosleep({100, 0},
...
exit_group(0) = ?
Como puedes ver, sucedió casi igual que cuando llamas de sleep
la forma normal. bash
comprueba si X_OK
se concede el permiso ejecutable ( ) /bin/sleep
con la access()
llamada al sistema. Luego execve()
ejecuta el programa señalado por el nombre del archivo. Después de execve()
la llamada al sistema, sleep
tiene el control sobre el proceso. ¿Son cosas: nanosleep()
. También mantiene el mismo pid. Una vez sleep
finalizado el proceso también finaliza. Si sleep
ni ya bash
no está funcionando.
Evidencia:
En otra ventana vi el proceso con ps
. Antes de ejecutar el comando se veía así:
$ ps -o stat,pid,cmd -p <pid>
Ss+ 10905 -bash
Y mientras corres:
$ ps -o stat,pid,cmd -p <pid>
Ss+ 10905 sleep 100
Afer sleep
terminó el proceso desaparecido.
¿Qué pasó cuando lo ejecuto normalmente?
access("/bin/sleep", X_OK) = 0
...
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f6c9fd089d0) = 19261
...
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WSTOPPED|WCONTINUED, NULL) = 19261
...
--- SIGCHLD (Child exited) @ 0 (0) ---
Se verifica el permiso de ejecución. Luego se crea un proceso hijo clone()
. La bash
instancia ahora está en el grupo de procesos en segundo plano, sleep
está en el grupo de procesos en primer plano. Y por último, la wait4()
llamada espera hasta que finalice el proceso hijo (eso necesita 100 segundos).