GNU/Linux >> Tutoriales Linux >  >> Linux

¿Por qué popen() invoca un shell para ejecutar un proceso?

La versión 2004 de POSIX system() la documentación tiene una razón que probablemente sea aplicable a popen() también. Tenga en cuenta las restricciones establecidas en system() , especialmente el que indica "que el ID del proceso es diferente":

FUNDAMENTO

...

Hay tres niveles de especificación para la función system(). El estándar ISO C da lo más básico. Requiere que la función exista y define una forma para que una aplicación consulte si existe un intérprete de lenguaje de comandos. No dice nada sobre el lenguaje de comandos o el entorno en el que se interpreta el comando.

IEEE Std 1003.1-2001 impone restricciones adicionales en system(). Requiere que si hay un intérprete de lenguaje de comandos, el entorno debe ser el especificado por fork() y exec. Esto asegura, por ejemplo, que close-on-exec funcione, que los bloqueos de archivos no se hereden y que el ID del proceso sea diferente. También especifica el valor de retorno de system() cuando se puede ejecutar la línea de comando, lo que brinda a la aplicación información sobre el estado de finalización del comando.

Finalmente, IEEE Std 1003.1-2001 requiere que el comando se interprete como en el lenguaje de comandos de shell definido en el volumen Shell and Utilities de IEEE Std 1003.1-2001.

Tenga en cuenta las múltiples referencias a la "Norma ISO C". La última versión del estándar C requiere que la cadena de comandos sea procesada por el "procesador de comandos" del sistema:

7.22.4.8 El system función

Sinopsis

#include <stdlib.h>
int system(const char *string);

Descripción

Si string es un puntero nulo, el system La función determina si el entorno host tiene un procesador de comandos. Si string no es un puntero nulo, el system la función pasa la cadena a la que apunta string a ese procesador de comandos para ser ejecutado de una manera que la implementación deberá documentar; esto podría causar que el programa llame a system comportarse de manera no conforme o terminar.

Devoluciones

Si el argumento es un puntero nulo, el system function devuelve un valor distinto de cero solo si hay un procesador de comandos disponible. Si el argumento no es un puntero nulo y system función devuelve, devuelve un valor definido por la implementación.

Dado que el estándar C requiere que el "procesador de comandos" del sistema se use para el system() llamada, sospecho que:

  1. En algún lugar hay un requisito en POSIX que vincula popen() al system() implementación.
  2. Es mucho más fácil simplemente reutilizar el "procesador de comandos" por completo, ya que también existe el requisito de ejecutarlo como un proceso separado.

Así que esta es la respuesta simplista eliminada dos veces.


Invocar un shell le permite hacer todas las cosas que puede hacer en un shell. Por ejemplo,

FILE *fp = popen("ls *", "r");

es posible con popen() (expande todos los archivos en el directorio actual). Compárelo con:

execvp("/bin/ls", (char *[]){"/bin/ls", "*", NULL});

No puedes ejecutar ls con * como argumento porque exec(2) interpretará * literalmente.

Del mismo modo, las tuberías (| ), redirección (> , < , ...), etc., son posibles con popen .

De lo contrario, no hay razón para usar popen si no necesita shell, es innecesario. Terminará con un proceso de shell adicional y todas las cosas que pueden salir mal en un shell pueden salir mal en su programa (por ejemplo, el comando que pasa podría ser interpretado incorrectamente por el shell y un problema de seguridad común). popen() está diseñado de esa manera. fork + exec la solución es más limpia sin los problemas asociados con un caparazón.


La respuesta simplista es porque el estándar POSIX ( http://pubs.opengroup.org/onlinepubs/9699919799/functions/popen.html ) lo dice. O más bien, dice que debería comportarse como si el argumento del comando se pasara a /bin/sh para su interpretación.

Entonces, supongo que una implementación conforme podría, en principio, también tener alguna función de biblioteca interna que interpretaría los comandos de shell sin tener que bifurcar y ejecutar un proceso de shell separado. En realidad, no estoy al tanto de ninguna implementación de este tipo, y sospecho que corregir todos los casos de esquina sería bastante complicado.


Linux
  1. ¿Por qué Bashrc comprueba si el shell actual es interactivo?

  2. ¿Por qué un shell de inicio de sesión 'sudo -i' interrumpe un argumento de cadena de comando Here-doc?

  3. ¿Por qué el siguiente comando está matando un sistema?

  4. ¿Por qué "ls" requiere un proceso separado para su ejecución?

  5. ¿Qué significa &al final de un comando de Linux?

Cómo usar el comando htop para monitorear los procesos del sistema en tiempo real

Cómo ejecutar un comando de Shell con Python

Cómo ejecutar comandos de Shell a través del servidor HTTP

¿Cómo ejecutar un comando en un script de Shell?

¿Por qué Ctrl + V no se pega en Bash (shell de Linux)?

¿Por qué mi sistema Linux repite cada comando que escribo?