GNU/Linux >> Tutoriels Linux >  >> Linux

Pourquoi popen() invoque-t-il un shell pour exécuter un processus ?

La version 2004 du POSIX system() la documentation a une justification qui s'applique probablement à popen() aussi bien. Notez les restrictions indiquées sur system() , en particulier celui indiquant "que l'ID de processus est différent" :

JUSTIFICATION

...

Il existe trois niveaux de spécification pour la fonction system(). La norme ISO C donne les plus élémentaires. Il nécessite que la fonction existe et définit un moyen pour une application de demander si un interpréteur de langage de commande existe. Il ne dit rien sur le langage de commande ou l'environnement dans lequel la commande est interprétée.

IEEE Std 1003.1-2001 impose des restrictions supplémentaires sur system(). Il nécessite que s'il existe un interpréteur de langage de commande, l'environnement doit être tel que spécifié par fork() et exec. Cela garantit, par exemple, que la fermeture à l'exécution fonctionne, que les verrous de fichiers ne sont pas hérités et que l'ID de processus est différent. Il spécifie également la valeur de retour de system() lorsque la ligne de commande peut être exécutée, donnant ainsi à l'application des informations sur l'état d'achèvement de la commande.

Enfin, IEEE Std 1003.1-2001 exige que la commande soit interprétée comme dans le langage de commande shell défini dans le volume Shell and Utilities de IEEE Std 1003.1-2001.

Notez les multiples références à la "norme ISO C". La dernière version de la norme C exige que la chaîne de commande soit traitée par le "processeur de commande" du système :

7.22.4.8 Le system fonction

Synopsis

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

Description

Si string est un pointeur nul, le system La fonction détermine si l'environnement hôte dispose d'un processeur de commande. Si string n'est pas un pointeur nul, le system la fonction passe la chaîne pointée par string à ce processeur de commandes à exécuter d'une manière que la mise en œuvre doit documenter ; cela pourrait alors amener le programme à appeler system de se comporter de manière non conforme ou de résilier.

Retours

Si l'argument est un pointeur nul, le system la fonction renvoie une valeur différente de zéro uniquement si un processeur de commandes est disponible. Si l'argument n'est pas un pointeur nul et que le system fonction renvoie, elle renvoie une valeur définie par l'implémentation.

Étant donné que la norme C exige que le "processeur de commandes" du système soit utilisé pour le system() appeler, je soupçonne que :

  1. Quelque part, il y a une exigence dans POSIX qui lie popen() au system() mise en œuvre.
  2. Il est beaucoup plus simple de réutiliser entièrement le "processeur de commandes", car il est également nécessaire de l'exécuter en tant que processus distinct.

C'est donc la réponse désinvolte supprimée deux fois.


L'invocation d'un shell vous permet de faire tout ce que vous pouvez faire dans un shell. Par exemple,

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

est possible avec popen() (développe tous les fichiers du répertoire courant). Comparez-le avec :

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

Vous ne pouvez pas exécuter ls avec * comme argument car exec(2) interprétera * littéralement.

De même, les pipes (| ), redirection (> , < , ...), etc., sont possibles avec popen .

Sinon, il n'y a aucune raison d'utiliser popen si vous n'avez pas besoin de shell - c'est inutile. Vous vous retrouverez avec un processus shell supplémentaire et toutes les choses qui peuvent mal tourner dans un shell go peuvent mal tourner dans votre programme (par exemple, la commande que vous passez peut être mal interprétée par le shell et un problème de sécurité courant). popen() est conçu ainsi. fork + exec la solution est plus propre sans les problèmes associés à un shell.


La réponse désinvolte est parce que la norme POSIX ( http://pubs.opengroup.org/onlinepubs/9699919799/functions/popen.html ) le dit. Ou plutôt, il dit qu'il doit se comporter comme si l'argument de la commande était passé à /bin/sh pour interprétation.

Je suppose donc qu'une implémentation conforme pourrait, en principe, avoir également une fonction de bibliothèque interne qui interpréterait les commandes shell sans avoir à bifurquer et à exécuter un processus shell séparé. Je ne suis pas au courant d'une telle implémentation, et je pense qu'il serait assez difficile de corriger tous les cas particuliers.


Linux
  1. ne pas échouer la construction de jenkins si l'exécution du shell échoue

  2. Que signifie la syntaxe |&en langage shell ?

  3. Pourquoi exécuter une commande shell Linux avec '&' ?

  4. Pourquoi Ctrl + V ne colle-t-il pas dans Bash (shell Linux) ?

  5. Pourquoi mon système Linux répète-t-il chaque commande que je tape ?

Comment utiliser la commande htop pour surveiller les processus système en temps réel

Comment exécuter une commande Shell avec Python

Qu'est-ce que POSIX ? Pourquoi est-ce important pour les utilisateurs Linux/UNIX ?

Comment exécuter des commandes Shell via un serveur HTTP

Pourquoi "ls" nécessite-t-il un processus distinct pour l'exécution ?

Comment exécuter une commande dans un script shell ?