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
funzioneSinossi
#include <stdlib.h> int system(const char *string);
Descrizione
Se
string
è un puntatore nullo, ilsystem
La funzione determina se l'ambiente host dispone di un processore dei comandi. Sestring
non è un puntatore nullo, ilsystem
La funzione passa la stringa puntata dastring
a quel processore di comandi da eseguire in un modo che l'implementazione deve documentare; questo potrebbe quindi far sì che il programma chiamisystem
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 ilsystem
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:
- Da qualche parte c'è un requisito in POSIX che lega
popen()
alsystem()
implementazione. - È 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.