Pred popsanim nastroju pro rizeni procesu se musime nejdriv zabyvat prostredim, ve kterem procesy bezi. Dale se budeme zabyvat otazkou dodatecne spravy pameti.
Kazdy program v C musi nutne obsahovat funkci main. Jeji prototyp je:
int main (int argc, char *argv[]);
Kde argc je pocet argumentu na prikazove radce a argv je ukazatel na pole argumentu. Pri spusteni programu nejprve probehnou start-up funkce, ktere zajisti vyplneni techto struktur.
je nekolik zakladnich cest, jak ukoncit proces:
Tyto dve funkce mohou primo ukoncit program. Funkce _exit primo vrati rizeni jadru a exit provede uklizeci procedury.
#include <stdlib.h> |
void exit (int status); |
#include <unistd.h> |
void _exit (int status) |
Klasicky priklad programu v C...
#include <stdio.h> main() { printf("hello, world\n"); }...je vlastne nespravny -- nema definovan navratovy kod.
Aby byl program uplny, meli bychom definovat navratovy kod takto:
return(0);nebo
exit(0);
Pri definovani navratovych kodu si ale musime uvedomit, ze druhe reseni povede k vystraznemu hlaseni -- konflikt prototypu.
Pri pouziti ANSI C muzeme pouzit az 32 funkci, ktere se automaticky provedou pri volani exit. Tyto funkce (exit handlers) muzeme registrovat pomoci funkce atexit.
#include <stdlib.h> |
int atexit (void (*func) (void)); |
Vraci: 0 kdyz OK, nenulova hodnota pri chybe |
Pri volani exit norma ANSI zarucuje, krome jineho, uzavreni otevrenych souboru. Obrazek 5 ukazuje, jak program v C startuje a jakymi moznymi zpusoby lze ukoncit.
Obrazek 5:
Jak program v C startuje a jak se ukoncuje
Priklad:
static void my_exit1(void), my_exit2(void); int main(void) { if (atexit(my_exit2) != 0) err_sys("can't register my_exit2"); if (atexit(my_exit1) != 0) err_sys("can't register my_exit1"); if (atexit(my_exit1) != 0) err_sys("can't register my_exit1"); printf("main is done\n"); return(0); } static void my_exit1(void) { printf("first exit handler\n"); } static void my_exit2(void) { printf("second exit handler\n"); }
Kdyz je program provaden, funkce exec dovoluje predat programu prikazovou radku.
Priklad:
Normalne prikaz echo neprovadi echo cele radky. Po zkompilovani nasledujiciho programu ziskame echo prikazoveho radku.
int main(int argc, char *argv[]) { int i; for (i = 0; i < argc; i++) /* echo all command-line args */ printf("argv[%d]: %s\n", i, argv[i]); exit(0); }
ANSI i POSIX.1 garantuji, ze argv[argc] je NULL pointer. To nam alternativne umozni psat:
for (i=0; argv[i] != NULL; i++)
Historicky se program skladal z techto casti:
int maxcount = 99;uvedena mimo jakoukoliv funkci, bude ulozena prave v teto oblasti.
long count[1000];
Viz tez obrazek 6.
Obrazek 6:
Typicke usporadani pameti
Sdilene knihovny byly popsany jiz v prvnich implementacich Systemu V. Hlavni princip spociva v odstraneni knihoven z programu a spolecne sdileni jedine jejich kopie v pameti. Pri spusteni vice programu najednou se vyrazne usetri pamet. Nejjednodussi cestou, jak pouzit sdilenych knihoven, je spravne nastaveni parametru programu cc a ld. Po zkompilovani se sdilenymi knihovnami rapidne poklesne velikost vystupniho souboru (jednotlive casti programu zjistime prikazem size).
V ANSI C jsou definovany tri zakladni funkce pro dynamicke pridelovani pameti.
#include <stdlib.h> |
void *malloc (size_t size); void *calloc (size_t nobj, size_t size); void *realloc (void *ptr, size_t newsize); |
Vsechny tri vraci: ukazatel kdyz OK, NULL pri chybe |
void free(void *ptr); |
Posledni je uvedena funkce free, ktera slouzi k uvolneni alokovaneho mista.
Kazdemu programu je take predano prostredi (seznam promennych prostredi popisujici). Adresa pole urcujiciho prostredi je ulozena v globalni promenne environ.
extern char **environ
Napr. prostredi, skladajici se ze ctyr retezcu, muze vypadat nasledovne. Viz obr. 7.
Obrazek 7:
Prostredi sestavajici ze ctyr retezcu
Konvence pro prostredi vypada takto: name=value. Vetsina preddefinovanych jmen je psana velkymi pismeny, ale je to jen umluva.
Unixove jadro nikdy necte promenne -- jejich interpretace zalezi na jednotlivych aplikacich.
ANSI C definuje funkci, ktera slouzi ke zjisteni hodnoty promenne prostredi.
#include <stdlib.h> |
char *getenv (const char *name); |
Vraci: ukazatel na value patrici k name kdyz OK, NULL pri chybe |
Obdobne funkce existuji i pro nastavovani promennych, ale ty nejsou prenositelne (putenv, setenv, unsetenv, claerenv).
Pokud to vas system umoznuje, zkompilujte tento program jednou staticky a jednou se sdilenymi knihovnami. Porovnejte veliskosti vyslednych souboru.
Ladislav Dobias