Man execlp (3): spuštění souboru ke spuštění. Speciální sémantika execlp() a execvp(). Dítě zemře dříve než rodič

Analýza životní cyklus proces zahájen operační systém UNIX

Jednou z mnoha povinností správce systému je zajistit správné spouštění uživatelských programů. Tento úkol je komplikován přítomností dalších programů spuštěných současně v systému. Podle různé důvody tyto programy nemusí fungovat, zamrzat nebo být vadné. Pochopení procesu vytváření, správy a ničení těchto úloh v operačním systému UNIX® je nejdůležitější krok k vytvoření spolehlivějšího systému.

Vývojáři studují, jak jádro řídí procesy, také proto, že aplikace, které dobře spolupracují s ostatními součástmi systému, vyžadují méně prostředků a je méně pravděpodobné, že způsobí systému problémy. správci systému. Aplikace, kterou je nutné neustále restartovat, protože vytváří zombie procesy (popsáno později), přirozeně není žádoucí. Porozumění UNIXové systémy znamená, že spravované procesy umožňují vývojářům vytvářet programy, které běží hladce pozadí. Není potřeba, aby se relace terminálu zobrazovala na něčí obrazovce.

Hlavním stavebním kamenem řízení těchto programů je proces. Proces je název daný programu prováděnému operačním systémem. Pokud znáte příkaz ps, měli byste být obeznámeni se seznamem procesů, jako je ten v .

Výpis1. Výstup příkazu ps
sunbox#ps -ef UID PID PPID C STIME TTY TIME CMD root 0 0 0 20:15:23 ? 0:14 sched root 1 0 0 20:15:24 ? 0:00 /sbin/init root 2 0 0 20:15:24 ? 0:00 pageout root 3 0 0 20:15:24 ? 0:00 fsflush démon 240 1 0 20:16:37 ? 0:00 /usr/lib/nfs/statd ...

První tři sloupce jsou důležité pro zvážení. První obsahuje seznam uživatelů, jejichž jménem procesy běží, druhý uvádí ID procesů a třetí obsahuje ID nadřazených procesů. Poslední sloupec obsahuje popis procesu, obvykle název běžící program. Každému procesu je přiřazen identifikátor nazývaný identifikátor procesu (PID). Proces má také rodiče, ve většině případů je uvedeno PID procesu, který proces spustil.

Existence nadřazeného PID (PPID) znamená, že jeden proces je vytvořen jiným procesem. Počáteční proces, který se spouští v systému, se nazývá init a je mu vždy přiřazeno PID 1. init je první skutečný proces, který jádro spouští při bootování. Hlavním úkolem init je spustit celý systém.

init a další procesy s PPID 0 jsou procesy jádra.

Pomocí systémového volání vidlice Systémové volání fork(2) vytvoří nový proces . Vidlice použitá v je zobrazena v jednoduchý příklad

C kód.
Výpis 2. Jednoduché použití vidlice(2) sunbox$ cat fork1.c #include #zahrnout

int main (void) ( pid_t p; /* fork vrátí typ pid_t */ p = fork(); printf("fork se vrátil %d\n", p); ) sunbox$ gcc fork1.c -o fork1 sunbox$ . /fork1 fork vráceno 0 fork vráceno 698

Kód v fork1.c jednoduše zavolá fork a zobrazí celočíselný výsledek spuštění fork prostřednictvím volání printf. Provede se pouze jedno volání, ale výstup se zobrazí dvakrát. K tomu dochází, protože se jako součást volání rozvětvení vytvoří nový proces. Po volání se vrátí dva samostatné procesy. To se často nazývá „jednou zavoláno, dvakrát vráceno“. Návratové hodnoty z forku jsou velmi zajímavé. Jedna z nich je 0; druhá je nenulová hodnota. Zavolá se proces, který obdrží 0 generované procesem a nenulová hodnota přejde do původního procesu, což je rodičovský proces

. Pomocí návratových hodnot určíte, který proces je který. Protože oba procesy obnovují provádění ve stejné oblasti, jediným možným rozlišovacím znakem jsou návratové hodnoty fork.

Důvodem pro návratové hodnoty null a non-null je to, že podřízený proces může vždy zjistit svého rodiče pomocí požadavku getppid(2), ale pro rodiče je mnohem obtížnější určit všechny jeho potomky. Rodič se tak dozví o svém novém dítěti a dítě může v případě potřeby svého rodiče najít. Nyní, když ví o návratové hodnotě fork, může kód rozlišovat mezi podřízeným a nadřazeným procesem a podle toho se chovat. B ukazuje program, který zobrazuje různé závěry

, na základě výsledků fork . Výpis 3. Víceúplný příklad
pomocí vidlice sunbox$ cat fork1.c #include int main (void) ( pid_t p; printf("Původní program, pid=%d\n", getpid()); p = fork(); if (p == 0) ( printf("V podřízeném procesu, pid =%d, ppid=%d\n", getpid(), getppid()); ) else ( printf("V nadřazeném prvku, pid=%d, fork vráceno=%d\n", getpid(), p) ; ) ) sunbox$ gcc fork2.c -o fork2 sunbox$ ./fork2 Původní program, pid=767 V podřízeném procesu, pid=768, ppid=767 V rodiči, pid=767, fork vrácen=768
Výpis 6. Rodičovský proces zemře dříve než dítě
#zahrnout sunbox$ cat fork1.c #include int main(void) ( int i; if (fork()) ( /* Nadřazený */ spánek(2); _exit(0); ) pro (i=0; i< 5; i++) { printf("My parent is %d\n", getppid()); sleep(1); } } sunbox$ gcc die1.c -o die1 sunbox$ ./die1 My parent is 2920 My parent is 2920 sunbox$ My parent is 1 My parent is 1 My parent is 1

V tomto příkladu nadřazený proces zavolá fork, počká dvě sekundy a ukončí se. Podřízený proces pokračuje a vytiskne PID svého rodiče po dobu pěti sekund. Můžete vidět, že když rodič zemře, PPID se změní na 1. Zajímavý je také návrat kontroly do shellu. Protože podřízený proces běží na pozadí, jakmile nadřazený zemře, řízení se vrátí do shellu.

Dítě zemře dříve než rodič

Popisuje opačný proces: smrt potomka před rodičem. Aby bylo možné lépe ukázat, co se děje, nic se netiskne přímo z procesu. Místo toho, zajímavé informace je v seznamu procesů.

Výpis 7. Podřízený proces zemře dříve než nadřazený proces
sunbox$ cat die2.c #include sunbox$ cat fork1.c #include int main(void) ( int i; if (!fork()) ( /* Dítě okamžitě odejde*/ _exit(0); ) /* Rodič čeká asi minutu */ sleep(60); ) sunbox$ gcc die2. c -o die2 sunbox$ ./die2 & 2934 sunbox$ ps -ef | grep 2934 sean 2934 2885 0 21:43:05 bodů/1 0:00 ./die2 sean 2935 2934 0 - ? 0:00 sunbox$ ps -ef | grep 2934 + výstup 199 ./die2

die2 běží na pozadí pomocí operátoru & a poté zobrazí seznam procesů, zobrazující pouze běžící proces a jeho potomky. PID 2934 je nadřazený proces, PID 2935 je proces, který je vytvořen a okamžitě ukončen. Navzdory předčasnému ukončení je spawnovaný proces stále v tabulce procesů, již jako mrtvý proces nazývaný také zombie. Když rodič po 60 sekundách zemře, oba procesy se ukončí.

Když podřízený proces zemře, jeho rodič je informován pomocí signálu zvaného SIGCHLD. Přesný mechanismus toho všeho nyní není důležitý. Opravdu záleží na tom, že rodič musí o smrti dítěte nějak vědět. Od okamžiku, kdy dítě zemře, dokud rodič nepřijme signál, je dítě ve stavu zombie. Zombie se nespustí a nespotřebuje zdroje CPU; zabírá pouze místo v tabulce procesů. Když rodič zemře, jádro může konečně odstranit děti spolu s rodičem. To znamená, že jediný způsob, jak se zbavit zombíků, je zabít rodiče. Nejlepší způsob vypořádejte se se zombíky - ujistěte se, že nevyjdou na vrchol. Kód B popisuje obsluhu signálu pro zpracování příchozího signálu SIGCHLD.

Výpis 8. Obsluha signálu v akci
#zahrnout sunbox$ cat fork1.c #include sunbox$ cat fork1.c #include sunbox$ cat fork1.c #include void sighandler(int sig) ( printf("V obsluze signálu pro signál %d\n", sig); /* wait() je hlavní pro potvrzení SIGCHLD */ wait(0); ) int main(void) ( int i ; /* Nastavíme obsluhu signálu na SIGCHLD */ sigset(SIGCHLD, &sighandler) if (!fork()) ( /* Potomek */ _exit(0); ) sleep(60 die3 sunbox$ ./die3); & 3116 sunbox$ In obsluha signálu pro signál 18 ps -ef | grep 3116 sean 3116 2885 0 22:37:26 bodů/1 0:00 ./die3

Trochu složitější než předchozí příklad, protože existuje funkce sigset, která nastavuje ukazatel funkce na obsluhu signálu. Kdykoli proces přijme zpracovaný signál, zavolá se funkce specifikovaná pomocí sigset. Pro signál SIGCHLD musí aplikace zavolat wait(3c), aby počkala na ukončení podřízeného procesu. Protože proces již skončil, je to nutné, aby jádro obdrželo potvrzení, že děti zemřely. Ve skutečnosti by měl rodič udělat víc, než jen potvrdit signál. Měl by také vyčistit data dítěte.

Po provedení die3 se zkontroluje seznam procesů. Obsluha signálu obdrží hodnotu 18 (SIGCHLD), provede se potvrzení dokončení dítěte a rodič se vrátí do stavu spánku (60).

Stručné závěry

UNIXové procesy se vytvářejí, když jeden proces zavolá vidlici, která rozdělí běžící proces na dva. Proces pak může provést jedno ze systémových volání v rodině exec, které nahradí aktuální obraz novým.

Když nadřazený proces zemře, všechny jeho potomky jsou adoptovány init , který má PID 1. Pokud dítě zemře dříve než rodič, je předán signál nadřazenému procesu a dítě přejde do stavu zombie, dokud signál je potvrzeno nebo je nadřazený proces ukončen.

Nyní, když víte, jak jsou procesy vytvářeny a ničeny, bude pro vás snazší porozumět procesům běžícím ve vašem systému. To platí zejména pro procesy se složitou strukturou, které jsou komplikovány mnoha dalšími procesy, jako je Apache. Schopnost sledovat strom procesu pro jeden proces vám umožňuje sledovat jakoukoli aplikaci zpět k procesu

Funkce Funkce, které načítají a spouštějí jiné programy. Syntaxe int execl(char * cesta, char * arg0, arg1, ..., argn, NULL); int execle(char * cesta, char * arg0, arg1, ..., argn, NULL, char ** envp); int execlp(char * název cesty, znak * arg0, arg1, ..., argn, NULL); int execlpe(char * cesta, char * arg0, arg1, ..., argn, NULL, char ** envp); int execv(char * cesta, char * argv); int execve(char * cesta, char * argv, char ** envp); CESTA DOS. Bez přípony p bude vyhledávání provedeno pouze v pracovním adresáři. Pokud parametr path neobsahuje trasu, pak se hledání provede v aktuálním adresáři a poté podél tras definovaných proměnnou prostředí PATH. l - označuje, že ukazatele adresy (arg0, arg1, ..., argn) jsou předávány jako samostatné argumenty. Přípona l se obvykle používá, když předem znáte počet argumentů, které mají být předány. v - označuje, že ukazatele adresy (arg, arg,...arg[n]) jsou předány jako pole ukazatelů. Typicky se při vysílání používá přípona v variabilní číslo argumenty. e – označuje, že procesu „dítě“ lze předat argument envp, který vám umožňuje vybrat prostředí „dítě“ procesu. Bez přípony e zdědí „dítě“ proces prostředí „rodičovského“ procesu. Každá funkce v rodině exec... musí mít jednu ze dvou přípon určujících argumenty (buď l nebo v). Definice cesty (PATH) a přípony dědičnosti operační prostředí(p ae) jsou volitelné. Například: - execl - je funkcí rodiny exec..., která předává samostatné argumenty, hledá "podřízený" proces pouze v pracovním adresáři a "rodičovské" prostředí předává "podřízenému" procesu., která je přiřazena každé proměnné envvar. Poslední prvek v poli envp je adresa nula NULL. Když má envp hodnotu NULL, „podřízený“ proces zdědí přiřazení prostředí „nadřazeného“ procesu. Celková délka arg0+ arg1+...+argn (nebo arg+ arg+...+arg[n]), včetně mezer oddělujících argumenty, musí být menší než 128 bajtů. Nulové konce se nepočítají. Když se zavolá exec..., jakýkoli sunbox$ cat fork1.c #include otevřít soubory zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. EACCES – Přístup odepřen.<=argc;loop++) puts(argv); return 0; } #includezůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. EMFILE – Příliš mnoho otevřených souborů.<=argc;loop++) puts(argv); /* напечатать первый параметр среды */ printf("env = %s\n",env); return 0; } #includezůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. ENOENT – Nebyla nalezena přístupová cesta (PATH) nebo název souboru.<=argc;loop++) puts(argv); return 0; } #includezůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. Chyba formátu ENOEXEC - EXEC. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. void main(int argc,char **argv) ( printf("Začíná CHILD s arg1, arg2 ...\n"); execv("CHILD.EXE",argv); perror("Chyba EXEC"); exit( 1); ) #zahrnout zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. void main(int argc,char **argv,char **envp) ( printf("Spustit CHILD s arg1, arg2 ...\n"); execve("CHILD.EXE",argv,envp); perror(" EXEC chyba"); exit(1); ) #include zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. void main(int argc,char **argv) ( printf("Začíná CHILD s arg1, arg2 ...\n"); execvp("CHILD.EXE",argv); perror("Chyba EXEC"); exit( 1); ) #zahrnout zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. zůstávají otevřené v procesu „dítě“. Vráceno Po úspěšném dokončení funkce exec... není vrácena žádná hodnota. Pokud dojde k chybě, funkce exec... vrátí hodnotu -1 a globální proměnná errno se nastaví na jednu z následujících hodnot: E2BIG - Seznam argumentů je příliš dlouhý. int main(int argc,char **argv,char **envp) ( printf("Spustit CHILD s arg1, arg2 ...\n"); execvpe("CHILD.EXE",argv,envp); perror(" EXEC chyba"); exit(1); )

int execle(char *fname, char *arg0, ..., char *argN, NULL, char *envp)

int execlp(znak *jméno, znak *arg0, ..., znak *argN, NULL)

int execlpe(znak *jméno, znak *arg0, ..., znak *argN, NULL, znak *envp)

int execv(znak *jméno, znak *arg)

int execve(char *fname, char *arg, char *envp)

int execvp(znak *jméno, znak *arg)

int execvpe(char *fname, char *arg, char *envp)

Popis:

Tyto funkce nejsou definovány standardem ANSI C.

Funkční skupina exec slouží ke spuštění jiného programu. Tento další program, nazývaný podřízený proces, je načten nad program obsahující volání exec. Název souboru obsahujícího podřízený proces je určen pomocí parametru fname. Jakékoli argumenty předané podřízenému procesu jsou určeny buď parametry arg0 až argN nebo polem arg. Parametr envp musí ukazovat na řetězec prostředí. (Argumenty, na které poukazuje argv v podřízeném procesu.)

Pokud fname neobsahuje příponu nebo tečku, vyhledá se nejprve podle názvu souboru. V případě neúspěchu se přidá přípona EXE a hledání se opakuje. V případě neúspěchu se použije přípona COM a hledání se opakuje znovu. Pokud je přípona zadaná, pak se vyhledá pouze přesná shoda. Nakonec, pokud existuje tečka, ale není specifikována žádná přípona, pak se vyhledávání provádí na levé straně názvu souboru.

Přesný způsob, jakým je podřízený proces spuštěn, závisí na verzi funkce exec, která je volána. Funkci exec si můžete představit tak, že má různé přípony, které určují její operace. Přípona se může skládat z jednoho nebo dvou znaků.

Funkce s příponou p hledají podřízený proces v adresářích určených příkazem PATH. Pokud přípona p chybí, vyhledávání se provádí pouze v aktuálním adresáři.

Pokud je zadaná přípona l, znamená to, že argumenty jsou podřízenému procesu předány jednotlivě, nikoli v poli. Tato metoda se používá při předávání pevného počtu argumentů. Upozorňujeme, že poslední argument musí být NULL. (NULL je definována v stdio.h.)

Přípona v znamená, že argumenty jsou předány podřízenému procesu v poli. Tato metoda se používá, když není předem známo, kolik argumentů bude předáno podřízenému procesu, nebo se počet argumentů může během provádění programu změnit. Obvykle je konec pole označen nulovým ukazatelem.

Přípona e označuje, že podřízenému procesu bude předán jeden nebo více řetězců prostředí. Parametr envp je pole ukazatelů na řetězce. Každý řádek, na který ukazuje pole, musí vypadat takto: proměnná_prostředí = hodnota

Poslední ukazatel v poli musí být NULL. Pokud je první prvek pole NULL, potom podřízený proces udržuje stejné prostředí jako proces předchůdce.

Je důležité si uvědomit, že soubory otevřené exec jsou také otevřeny v podřízeném programu.

Pokud je úspěšný, exec nevrací hodnotu. Při selhání je vráceno -1 a errno je nastaveno na jednu z následujících hodnot:

První z následujících programů volá druhý, který vypíše své argumenty. Upozorňujeme, že oba programy musí být v samostatných souborech.

/* první soubor je nadřazený */
#zahrnout
#zahrnout
#zahrnout
int main (void)
{
execl("test.exe" , "test.exe" , "ahoj" , "10" , NULL);
návrat 0;
}

/* druhý soubor je potomek */
#zahrnout
#zahrnout
int main(int argc, char * argv)
{
printf( "Tento program se spouští pomocí těchto příkazových řádků") ;
printf ("argumenty: " );
printf (argv[ 1] );
printf (" %d" , atoi (argv[ 2 ] ) );
návrat 0;
}

rodina funkcí exec().

Rodina funkcí exec() nahrazuje program běžící v aktuálním procesu jiným programem. Když program zavolá funkci exec(), jeho provádění se okamžitě zastaví a spustí se nový program.

Funkce obsažené v rodině exec() se mírně liší svými schopnostmi a způsobem jejich volání.

Funkce s příponou "p" ve svých názvech (execvp() a execlp()) berou název programu jako argument a hledají tento program v adresářích určených proměnnou prostředí PATH. Všechny ostatní funkce musí předat úplnou cestu k programu.

Funkce s příponou "v" ve svých názvech (execv(), execvp() a execve()) přijímají seznam argumentů programu jako pole řetězcových ukazatelů, které končí ukazatelem NULL. Funkce s příponou "l" (execl(), execlp() a execle()) přijímají seznam argumentů proměnné délky.

Funkce s příponou "e" ve svých názvech (execve() a execle()) berou jako další argument pole proměnných prostředí. Toto pole obsahuje řetězcové ukazatele a končí nulovým ukazatelem. Každý řádek by měl vypadat jako " VARIABILNÍ=význam" .

Protože exec() nahrazuje jeden program jiným, nikdy nevrací hodnotu – pouze v případě, že program nebylo možné volat kvůli chybě.

Seznam argumentů předávaných programu je podobný argumentům příkazového řádku zadaným při interaktivním spouštění programu. Lze je také získat pomocí parametrů argc a argv funkce main(). Pamatujte, že když je program spuštěn interpretem příkazů, první prvek pole argv bude obsahovat název programu, za nímž budou následovat argumenty předané programu. Totéž byste měli udělat při generování seznamu argumentů pro funkci exec().

EXEC(2)

JMÉNO
exec: spuštění souboru execl, execv, execle, execve, execlp, execvp

SYNTAX

Int execl (cesta, arg0, arg1, ..., argn, (znak*) 0) char *cesta, *arg0, *arg1, ..., *argn;

int execv (cesta, argv) char *cesta, *argv ;
int execle (cesta, arg0, arg1, ..., argn, (znak*) 0, envp) char *cesta, *arg0, *arg1, ..., *argn, *envp ;

int execve (cesta, argv, envp) char *cesta, *argv , *envp ;

int execlp (soubor, arg0, arg1, ..., argn, (znak*) 0) char *soubor, *arg0, *arg1, ..., *argn;

kde argc se rovná počtu argumentů, argv je pole ukazatelů na samotné argumenty a envp je pole ukazatelů na řetězce znaků, které tvoří prostředí. Platí konvence, že argc je alespoň 1 a první prvek pole argv ukazuje na řetězec znaků obsahující název nového spustitelného souboru.

Argumenty systémových volání exec group mají následující význam.

Argument path určuje cestu k novému spustitelnému souboru.

Stejně jako cesta i argument file určuje nový spustitelný soubor, ale cesta k souboru je určena pohledem na adresáře procházející proměnnou prostředí PATH [viz prostředí(5) ]. Prostředí je udržováno pomocí shellu [viz sh(1) ].

Argumenty arg0, arg1, ..., argn jsou ukazatele na znakové řetězce oddělené nulovými bajty. Tyto řetězce tvoří seznam argumentů dostupných pro nový proces. Podle konvence musí být přítomen minimálně arg0 a musí ukazovat na řetězec znaků rovný cestě (nebo poslední komponentě cesty).

Pole argv obsahuje ukazatele na znakové řetězce oddělené prázdnými bajty. Tyto řetězce tvoří seznam argumentů dostupných pro nový proces. Podle konvence musí argv obsahovat alespoň první prvek ukazující na řetězec znaků rovný cestě (nebo poslední komponentě cesty). Za posledním obsazeným prvkem pole argv musí následovat nulový ukazatel.

Pole envp obsahuje ukazatele na znakové řetězce oddělené nulou bajtů. Tyto řetězce tvoří prostředí nového procesu. Za posledním obsazeným prvkem pole envp musí následovat nulový ukazatel.

Před spuštěním jakéhokoli spuštění programu do vnějšího prostředí proměnné, jejíž popis vypadá

Extern char **prostředí;

je umístěna adresa pole ukazatelů na řetězce symbolů, které tvoří prostředí procesu. Pomocí této proměnné (stejně jako pomocí argumentu envp to main) lze k prostředí přistupovat vždy v novém procesu, bez ohledu na to, která verze systémového volání exec byla použita. Jediný rozdíl je v tom, že v případě volání execle a execve je prostředí nového procesu specifikováno explicitně a v ostatních případech je zděděno z volajícího procesu.

Soubory otevřené ve volajícím procesu zůstávají otevřené v novém procesu, s výjimkou těch, které mají nastaven příznak "close on exec" [viz fcntl(2)]. Pokud soubor zůstane otevřený, uloží se ukazatel na aktuální pozici v souboru.

Odezva na signály je zachována, kromě toho, že signály, které byly zachyceny ve volajícím procesu, způsobí ukončení nového procesu [viz signál(2) ].

V případě, kdy byla signálová odezva nastavena voláním sigset(2) a specifikována jako SIG_DFL, SIG_IGN nebo SIG_HOLD, je tato odpověď zděděna z volajícího procesu. Pokud je však signál zachycen, pak je nastavena odpověď SIG_DFL a všechny přijaté, ale nezpracované signály tohoto typu jsou odloženy.

Pokud má nový spustitelný soubor bit oprávnění nastavený na resetování aktuálního ID uživatele [viz chmod(2) ], pak se efektivní ID uživatele nového procesu nastaví na ID vlastníka nového spustitelného souboru. Podobně, pokud je bit oprávnění nového spustitelného souboru nastaven na resetování ID efektivní skupiny, pak se ID efektivní skupiny nového procesu nastaví na ID skupiny nového spustitelného souboru. Skutečné ID uživatele a ID skutečné skupiny nového procesu se dědí z volajícího procesu.

Připojené segmenty sdílené paměti nejsou zděděny novým procesem [viz shmop(2)].

Nový proces má zakázáno profilování.

Kromě toho nový proces zdědí následující vlastnosti z procesu, který se nazývá exec:

  1. Hodnota nastavení priority [viz pěkné (2)].
  2. ID procesu.
  3. ID nadřazeného procesu.
  4. ID skupiny procesů.
  5. semadj významy [viz semop(2) ].
  6. ID skupiny terminálů [viz exit(2) ].
  7. Režim trasování [viz ptrace(2)].
  8. Čas zbývající do spuštění budíku [viz alarm(2) ].
  9. Aktuální pracovní adresář.
  10. Kořenový adresář.
  11. Maska režimu vytváření souboru [viz. umask(2)].
  12. Limit velikosti souboru [viz ulimit(2)].
  13. Počítadla času stráveného údržbou tohoto procesu (tms_utime, tms_stime, tms_cutime, tms_cstime) [viz krát(2)].
  14. Blokování přístupu k segmentům souborů [viz. fcntl(2) a lockf(3C)].

Systémové volání exec selže a řízení se vrátí, pokud platí alespoň jedna z následujících podmínek: Komponenta trasy nového spustitelného souboru neexistuje.




Nejnovější články