Verze POSIX system()
z roku 2004 dokumentace má zdůvodnění, které je pravděpodobně použitelné pro popen()
také. Všimněte si uvedených omezení na system()
, zejména ten, který uvádí „že ID procesu je jiné“:
ODŮVODNĚNÍ
...
Pro funkci system() existují tři úrovně specifikace. Norma ISO C poskytuje to nejzákladnější. Vyžaduje, aby funkce existovala, a definuje způsob, jakým se aplikace dotazuje, zda existuje interpret jazyka příkazů. Neříká nic o jazyce příkazu ani o prostředí, ve kterém je příkaz interpretován.
IEEE Std 1003.1-2001 klade na system() další omezení. Vyžaduje to, že pokud existuje interpret příkazového jazyka, prostředí musí být takové, jaké specifikují fork() a exec. To například zajišťuje, že close-on-exec funguje, že se zámky souborů nedědí a že ID procesu je odlišné. Určuje také návratovou hodnotu ze system(), kdy lze spustit příkazový řádek, čímž poskytuje aplikaci určité informace o stavu dokončení příkazu.
A konečně, IEEE Std 1003.1-2001 vyžaduje, aby byl příkaz interpretován jako příkazový jazyk shellu definovaný v Shell and Utilitiesvolume IEEE Std 1003.1-2001.
Všimněte si četných odkazů na "normu ISO C". Nejnovější verze standardu C vyžaduje, aby byl příkazový řetězec zpracován „příkazovým procesorem“ systému:
7.22.4.8
system
funkceSynopse
#include <stdlib.h> int system(const char *string);
Popis
Pokud
string
je nulový ukazatel,system
Funkce určuje, zda hostitelské prostředí má příkazový procesor. Pokudstring
není nulový ukazatel,system
funkce předá řetězec, na který ukazujestring
tomuto příkazovému procesoru, který má být proveden způsobem, který implementace dokumentuje; to může způsobit, že program volásystem
chovat se nekonformně nebo ukončit.Vrátí se
Pokud je argumentem nulový ukazatel,
system
funkce vrací nenulovou hodnotu pouze v případě, že je k dispozici příkazový procesor. Pokud argument není nulový ukazatel, asystem
functiondoes return, vrátí implementačně definovanou hodnotu.
Protože standard C vyžaduje, aby byl pro system()
použit systémový "příkazový procesor". zavolejte, mám podezření, že:
- Někde je v POSIX požadavek, který spojuje
popen()
nasystem()
implementace. - Je mnohem snazší znovu použít celý „příkazový procesor“, protože je zde také požadavek, aby běžel jako samostatný proces.
Takže toto je glib odpověď dvakrát odstraněna.
Vyvolání shellu vám umožní dělat všechny věci, které můžete dělat v shellu. Například
FILE *fp = popen("ls *", "r");
je možné pomocí popen()
(rozbalí všechny soubory v aktuálním adresáři). Porovnejte s:
execvp("/bin/ls", (char *[]){"/bin/ls", "*", NULL});
Nemůžete spustit ls
s *
jako argument, protože exec(2)
bude interpretovat *
doslova.
Podobně potrubí (|
), přesměrování (>
, <
, ...), atd., jsou možné pomocí popen
.
V opačném případě není důvod používat popen
pokud shell nepotřebujete - je to zbytečné. Skončíte s procesem shellu navíc a všechny věci, které se mohou v shellu pokazit, se mohou pokazit ve vašem programu (např. příkaz, který předáte, může být shellem nesprávně interpretován a běžný bezpečnostní problém). popen()
je navržena tak. fork
+ exec
řešení je čistší bez problémů spojených s shellem.
Glib odpověď je proto, že to říká standard POSIX ( http://pubs.opengroup.org/onlinepubs/9699919799/functions/popen.html ). Nebo spíše říká, že by se měl chovat, jako kdyby byl argument příkazu předán do /bin/sh pro interpretaci.
Předpokládám tedy, že vyhovující implementace by v zásadě mohla mít také nějakou funkci vnitřní knihovny, která by interpretovala příkazy shellu, aniž by bylo nutné rozvětvovat a provádět samostatný proces shellu. Ve skutečnosti si nejsem vědom žádné takové implementace a mám podezření, že by bylo dost složité správně nastavit všechny rohové případy.