GNU/Linux >> Linux Esercitazione >  >> Linux

Perché popen() invoca una shell per eseguire un processo?

La versione 2004 del POSIX system() la documentazione ha una motivazione che è probabilmente applicabile a popen() anche. Nota le restrizioni dichiarate su system() , in particolare quello che afferma "che l'ID del processo è diverso":

MOZIONALE

...

Ci sono tre livelli di specifica per la funzione system(). Lo standard ISO C fornisce i più basilari. Richiede che la funzione esista e definisce un modo per un'applicazione di interrogare se esiste un interprete del linguaggio dei comandi. Non dice nulla sulla lingua del comando o sull'ambiente in cui il comando viene interpretato.

IEEE Std 1003.1-2001 pone ulteriori restrizioni su system(). Richiede che se esiste un interprete del linguaggio di comando, l'ambiente deve essere come specificato da fork() e exec. Ciò garantisce, ad esempio, che close-on-exec funzioni, che i blocchi dei file non vengano ereditati e che l'ID del processo sia diverso. Specifica inoltre il valore restituito da system() quando la riga di comando può essere eseguita, fornendo così all'applicazione alcune informazioni sullo stato di completamento del comando.

Infine, IEEE Std 1003.1-2001 richiede che il comando sia interpretato come nel linguaggio dei comandi della shell definito nel volume Shell and Utilities di IEEE Std 1003.1-2001.

Si noti i molteplici riferimenti allo "Standard ISO C". L'ultima versione dello standard C richiede che la stringa di comando sia elaborata dal "processore di comando" del sistema:

7.22.4.8 Il system funzione

Sinossi

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

Descrizione

Se string è un puntatore nullo, il system La funzione determina se l'ambiente host dispone di un processore dei comandi. Se string non è un puntatore nullo, il system La funzione passa la stringa puntata da string a quel processore di comandi da eseguire in un modo che l'implementazione deve documentare; questo potrebbe quindi far sì che il programma chiami system comportarsi in modo non conforme o terminare.

Resi

Se l'argomento è un puntatore nullo, il system function restituisce un valore diverso da zero solo se è disponibile un processore di comandi. Se l'argomento non è un puntatore nullo, e il system functiondoes restituisce, restituisce un valore definito dall'implementazione.

Poiché lo standard C richiede che il "processore di comando" del sistema sia utilizzato per system() chiamata, sospetto che:

  1. Da qualche parte c'è un requisito in POSIX che lega popen() al system() implementazione.
  2. È molto più semplice riutilizzare completamente il "processore di comando" poiché è anche necessario eseguirlo come processo separato.

Quindi questa è la risposta semplice rimossa due volte.


Invocare una shell ti permette di fare tutte le cose che puoi fare in una shell. Per esempio,

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

è possibile con popen() (espande tutti i file nella directory corrente). Confrontalo con:

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

Non puoi eseguire ls con * come argomento perché exec(2) interpreterà * letteralmente.

Allo stesso modo, pipe (| ), reindirizzamento (> , < , ...), ecc., sono possibili con popen .

Altrimenti, non c'è motivo di usare popen se non hai bisogno di shell, non è necessario. Finirai con un processo shell aggiuntivo e tutte le cose che possono andare storte in una shell possono andare storte nel tuo programma (ad esempio, il comando che passi potrebbe essere interpretato in modo errato dalla shell e un problema di sicurezza comune). popen() è progettato in questo modo. fork + exec soluzione è più pulita senza i problemi associati a una shell.


La risposta facile è perché lo standard POSIX ( http://pubs.opengroup.org/onlinepubs/9699919799/functions/popen.html ) lo dice. O meglio, dice che dovrebbe comportarsi come se l'argomento del comando fosse passato a /bin/sh per l'interpretazione.

Quindi suppongo che un'implementazione conforme potrebbe, in linea di principio, avere anche qualche funzione di libreria interna che interpreterebbe i comandi della shell senza dover eseguire il fork ed eseguire un processo shell separato. In realtà non sono a conoscenza di alcuna implementazione di questo tipo e sospetto che correggere tutti i casi limite sarebbe piuttosto complicato.


Linux
  1. Cos'è POSIX? Perché è importante per gli utenti Linux/UNIX?

  2. Perché la sostituzione del comando Shell divora un carattere di nuova riga finale?

  3. Perché una shell di accesso "sudo -i" interrompe un argomento della stringa di comando Here-doc?

  4. Perché "ls" richiede un processo separato per l'esecuzione?

  5. Perché questa pipeline di shell termina?

Come utilizzare il comando htop per monitorare i processi di sistema in tempo reale

Come eseguire un comando Shell con Python

Come eseguire i comandi della shell tramite il server HTTP

Come eseguire un comando in uno script della shell?

Perché Ctrl + V non incolla in Bash (shell Linux)?

Perché il comando sudo richiede molto tempo per essere eseguito?