1.5 Apelurile exec
Un proces poate specifica direct programul pe care îl execută un proces fiu sau îşi poate schimba propriul program prin apelul sistem exec. Trebuie specificat faptul că există mai multe variante ale acestui apel, numai una dintre ele fiind în realitate implementată ca apel sistem, iar celelalte sunt doar funcţii de bibliotecă. Sunt posibile maxim 8 apeluri de tip exec, dar s-au implementat doar 6.
Primitiva
|
Argumente
|
Cale
|
Mediu
|
execl()
|
lista
|
director curent
|
Automat
|
execv()
|
vector
|
director curent
|
Automat
|
execlp()
|
lista
|
PATH
|
Automat
|
execvp()
|
vector
|
PATH
|
Automat
|
execle()
|
lista
|
director curent
|
Precizat
|
execve()
|
vector
|
director curent
|
Precizat
|
Fig. 3. Apelurile exec
Prototipurile tuturor variantelor sunt:
#include
int execl(const char *pathname, const char *arg0,.../*(char *)0*/);
int execv(const char *pathname, char *const argv[]);
int execle(const char *pathname, const char *arg0,.../*(char *)0, char * const envp[]*/);
int execve(const char *pathname, char *const argv[], char *const envp[]));
int execlp(const char *filename, const char *arg0,.../*(char *)0*/);
int execvp(const char *filename, char *const argv[]);
O primă diferenţă întrre apeluri este că la primele patru se foloseşte argumentul pathname, iar la ultimele două se foloseşte filename. Elementul sintatic caracteristic este prezenţa literei p în numele ultimelor 2 apeluri. Interpretarea este următoarea:
- dacă filename conţine un caracter slash, se consideră că el este un nume de cale
- în caz contrar se caută un fişier executabil cu acest nume în cataloagele specificate de variabila de mediu path.
A doua diferenţă între apeluri provine din modul de transmitere a argumentelor spre programul apelat: fie ca listă, fie ca vector.
O a treia diferenţă constă în modul în care se transmite lista variabilelor de mediu spre noul program. Cele două apeluri ale căror nume se termină cu ''e'' permit ca ultim argument al apelului un tablou de pointeri la variabilele de mediu. Pentru celelalte 4 apeluri se foloseşte implicit variabila de mediu în ambianţa noului program.
Se pot observa şi asemănări între apelurile exec:
- execlp(), execl(), execle() primesc argumentele ca parametri terminaţi prin pointerul NULL;
- execvp(), execv(), execve() primesc tablouri de pointeri la argumente;
- execlp() şi execvp() primesc un nume de fişier, care urmează să fie convertit în cale cu informaţiile din variabila de mediu PATH;
- execle() şi execve() sunt singurele care primesc şi tablouri de pointeri la variabilele de mediu.
Pornind de la relaţia dintre cele 6 apeluri, se constată că este suficient ca numai execve să fie implementat efectiv ca apel sistem.
Următorul program, care afişează argumentele ce i se transmit în linia de comandă şi variabilele de mediu, ilustrează utilizarea apelurilor exec:
int main(inr argc, char *argv[]){
int i;
char **ptr;
extern char **environ;
for(i=0; i;argc; i++)
printf(' ' argv[%d]: %s\n' ', i, argv[i]);
for(ptr=environ; *ptr != 0; ptr++)
printf(' '%s\n' ', *ptr);
exit(0);
}
Presupunem programul memorat sub formă de fişier executabil cu numele echoargenv în catalogul gazdă al utilizatorului, va fi lansat în execuţie de două ori în procese fii create în următorul program:
#include
#include
char *envinit[]={' ' USER=unknown' ',' 'PATH=/bin:/tmp' ', (char *)0};
int main(void) {
pid_t pid;
if( (pid=fork()) < 0) {
printf(' 'fork error\n' ');
exit(1);
}else if (pid==0)
if(execle(' '/home/ionel/echoargenv' ', ' 'echoargenv' ', ' 'arg1' ',' ' arg2'', (char *)0, envinit)<0) {
printf(''execle error\n' ');
exit(1);
}
if(waitpid (pid,0,0)<0) ) {
printf(''waitpid error\n' ');
exit(1);
}
if((pid=fork())<0) ) {
printf(''fork error\n' ');
exit(1);
}else if(pid==0)
if(execlp(''echoargenv'', ''echoargenv'',''ARGUMENT1'',(char *)0)<0) {
printf(''execlp error\n' ');
exit(1);
}
exit(0);
}
Pentru apelul execle, în specificarea numelui de cale a fost utilizat un nume de cale absolut. Este posibilă utilizarea unui nume de cale relativ, dar nu este posibilă utilizarea unor variabile de mediu în numele de cale, acesta trebuind să fie un simplu şir de caractere.
În exemplul dat se creează procese distincte în care se lansează în execuţie un nou program. Este posibil ca un proces să schimbe programul pe care îl execută cu un alt program, apelând una din formele de exec. Într-un asemenea caz, apelul la exec nu mai revine, pentru că imaginea noului program va acoperi în memorie imaginea vechiului program, deci punctul de revenire nu mai există.
În paragrafele anterioare s-a tratat execuţia programelor (în limbajul C) sub UNIX şi apelul funcţiilor de tip exec. Programul C se scrie într-un editor de texte, fiind salvat apoi cu un nume de forma program.c. Compilarea şi lansarea în execuţie se face de la un terminal prin apeluri sistem specifice compilatorului GNU, gcc. După cum s-a menţionat, există diverse opţiuni la compilarea unui program, precum şi unele facilităţi oferite de bibliotecile partajate. Apelurile funcţiilor de tip exec sunt importante pentru ca printr-un astfel de apel, un proces poate specifica direct programul pe care îl execută un proces fiu sau îşi poate schimba propriul program. Deşi există 8 variante a acestui apel, doar unul este în realitate apel sistem.
Dostları ilə paylaş: |