View
34
Download
0
Category
Preview:
Citation preview
Cuprins
Executia unui program C sub UNIX
Apelurile sistem exit si _exit
Functia atexit
Transmiterea argumentelor si a ambiantei
Segmentele unui program C
Biblioteci partajate
Procese sistem sau permanente
Apelurile sistem getpid si getppid
Apelul sistem fork
Exemplu
Apeluri sistem pentru gestionarea
proceselor
Sistemul de operare UNIX ofera suport pentru:
Specificarea unor conditii la executia unui singur
program (proces)
Creare si gestionarea proceselor
Realizarea comunicarii intre procese
Executia unui program C sub UNIX
inceperea executiei unui program se face cu apelulsistem exec
cautarea unui fisier ce contine cod executabil
incarcarea in memorie a continutului partial sau total
cedarea controlului catre program
compilatorul C si editorul de legaturi adauga
rutina de start C care va primi controlul la pornireaprogramului
din rutina de start se apeleaza functia main
rutina de start preia argumentele din linia de comanda sivariabilele de ambianta
Executia programului
dupa ce executia ajunge la main se pot
apela alte functii utilizator
solicita apeluri sistem
terminarea executiei
normal
revenirea naturala din functia main
apelul sistem exit
apelul sistem _exit
anormal
prin apelul abort
daca procesul primeste un semnal
Apelurile sistem exit si _exit
#include <stdlib>
void exit(int status);
#include <unistd.h>
void _exit(int status);
un singur argument prin care programele transmit starea de terminare a procesului
terminarea normala e semnalata prin valori
zero
< 127 – reprezinta ramura de cod unde s-a ajuns conform conventiei programului
terminarea anormala - valori > 128
Rolul apelului exit
terminarea programului
tratarea corespunzatoare a operatiilor de
intrare/iesire in curs - asteptare
golirea tampoanelor
inchiderea tuturor fisierelor deschise
controlul este redat nucleului prin apelul _exit
Functia atexit
ofera programatorului posibilitatea de a inregistra functiisuplimentare care sa fie apelabile de exit
#include <stdlib.h>
int atexit(void (*func)(void));
fiecare apel atexit inregistreaza o functie data prin nume in cadrul apelului
functiile nu pot avea parametri si nu pot returna valoare
apelul lor se va face in ordinea inversa a inregistrarii de catre apelul exit
se poate inregistra o functie de mai multe ori daca e necesar
Exemplu atexit
#include <stdlib.h>
static void func1(void),func2(void);
int main(void)
{
if(atexit(func1)!=0)
{
printf(“eroare la inregistrare func1”); exit(1);
}
if(atexit(func1)!=0)
{
printf(“eroare la inregistrare func1”); exit(1);
}
Exemplu atexit
if(atexit(func2)!=0)
{
printf(“eroare la inregistrare func2”); exit(1);
}
printf(“S-a terminat functia main”);
return 0;
}
static void func1(void)
{
printf(“Primul handler pentru exit\n”);
}
Rulare
$ ./atexit
S-a terminat functia main
Al doilea handler pentru exit
Primul handler pentru exit
Primul handler pentru exit
Transmiterea argumentelor si a
ambiantei
functia main poate prelua argumente din linia de comanda
numarul acestora argc
valorile lor sub forma de siruri de caractere argv, cu ultimulelement nul
variabilele de mediu sunt facute accesibile programului prinvariabila globala standard environ
valoarea ei este un pointer la un tablou de pointeri la siruride caractere
sirurile de caractere
sunt de forma nume=valoare
reprezinta variabilele de mediu
ultimul element trebuie sa fie nul
Exemplu cu argumente si environ
#include <stdlib.h>
extern char **environ;
int main(int argc,char *argv[])
{
int i;
char **p=environ;
for(i=0;<argc;i++)
printf(“argv[%d]: %s\n”,i,argv[i]);
while(*p!=0)
{
printf(“%s\n”,*p);
p++;
}
}
Segmentele unui program C
segmentul de text
contine instructiunile programului in limbaj masina
acces numai pentru citire
zona poate fi partajata de procese multiple
segmentul de date initializate
contine variabilele initializate in textul sursa al
programului din afara functiilor
Segmentele unui program C
segmentul de date neinitializate
variabilele declarate in afara functiilor float
mat[20][30];
alocare spatiu de 600 valori float
bss block started by symbol
stiva
variabilele declarate in interiorul functiilor
informatiile necesare revenirii din apeluri
Segmentele unui program C
zona heap
pentru variabilele alocate dinamic
plasata deasupra valorilor neinitializate
creste spre stiva
in fisierul executabil avem doar
segmentul de text
segmentul de date initializate
Biblioteci partajate
majoritatea implementarilor de UNIX admit utilizarea unorastfel de biblioteci
nu se vor include in fiecare program la editarea de legaturifunctiile de biblioteca apelate
e suficient ca in memorie sa se incarce o copie a acestora
la ea vor face acces toate programele care trebuie sautilizeze acea biblioteca
pentru a utiliza biblioteci partajate la compilare
$ gcc –o argenv argenv.c
$ gcc –o argenvs –shared argenv.c
$ ls –l argenv argenvs
Apeluri sistem pentru crearea
proceselor
fiecare proces are identificator unic pid
intreg nenegativ atribuit de sistem la crearea
procesului
valori pana la o limita maxima dependenta de
implementare
pid-urile sunt unice si crescatoare
Procesele sistem sau permanente
procesul cu identificatorul 0 – swapper
responsabil cu planificarea la executie a proceselor
creat in timpul incarcarii nucleului
nu corespunde unui fisier pe disc
procesul cu identificatorul 1
creat la sfarsitul incarcarii nucleului
executa programul /etc/init
proces utilizator ce ruleaza cu privilegii de root
are rol de a initializa sistemul intr-o stare cunoscuta
determina configuratia sistemului
executa /bin/login
este parintele tuturor proceselor orfane
procesul cu identificatorul 2 - pagedaemon
responsabil pentru suportul de memorie virtuala
Apelurile sistem getpid si getppid
#include <sys/type.h>
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);
Apelul sistem fork
Creaza un nou proces
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
returneaza -1 in caz de eroare
dupa un apel reusit s-a creat un proces nou
procesul care a apelat fork devine proces parinte
procesul nou creat este procesul fiu
returneaza procesului parinte pid-ul fiului
procesul fiu este o copie a procesului parinte
dupa creare procesului fiu nu se stie daca se vacontinua cu executia fiului sau a parintelui
Exemplu pentru apelul sistem fork
#include <sys/types.h>
#include <unistd.h>
int glob=66;
char buf[]=“scriere la stdout\n”;
int main()
{
int var;
pid_t pid;
var=88;
Exemplu pentru apelul sistem fork
if(write(STDOUT_FILENO,buf,sizeof(buf)-1)!=
sizeof(buf)-1)
{
printf(“Eroare la scriere”);
exit(1);
}
printf(“mesaj inainte de fork”);
Exemplu pentru apelul sistem fork
if((pid=fork())<0)
{
printf(“eroare fork”);
exit(2);
}
else
{
if(pid==0){ glob++; var++; }
else sleep(2);
}
Exemplu pentru apelul sistem fork
printf(“pid=%d, glob=%d, var=%d”,
getpid(), glob, var);
exit(0);
}
Rulare
$ fork1
scriere la stdout
mesaj inainte de fork
pid=1412, glob=67, var=89
pid=1411, glob=66, var=88
$ fork1 > out
$ cat out
scriere la stdout
mesaj inainte de fork
pid=1412, glob=67, var=89
mesaj inainte de fork
pid=1411, glob=66, var=88
Analiza programului
apelul fork este inclus intr-o structura if
se testeaza valoarea returnata pentru a putea decide dacaurmeaza codul fiului sau al parintelui
procesele fiu si parinte au pid-uri diferite
fiul are propriile segmente de date si stiva
valorile glob si var apar modificate numai in fiu
apelul sistem write este executat fara tampoane, imediat
apelul functiei printf este executat cu utilizarea tampoanelornucleului
cele doua rulari
utilizarea tamponului la
nivel de linie in terminal
nivel de bloc in fisier
Recommended