Crida al sistema Linux Exec

Linux Exec System Call



La trucada al sistema exec s'utilitza per executar un fitxer que resideix en un procés actiu. Quan es diu exec, el fitxer executable anterior es reemplaça i s'executa el fitxer nou.

Més exactament, podem dir que mitjançant la trucada al sistema exec se substituirà el fitxer o el programa antic del procés per un fitxer o programa nou. Es reemplaça tot el contingut del procés per un programa nou.







El segment de dades d'usuari que executa la trucada del sistema exec () se substitueix pel fitxer de dades el nom del qual es proporciona a l'argument mentre es crida exec ().



El nou programa es carrega al mateix espai de procés. El procés actual s’acaba de convertir en un procés nou i, per tant, no es canvia l’identificador de procés PID, ja que no estem creant un procés nou sinó que substituïm un procés per un altre en exec.



Si el procés que s’executa actualment conté més d’un fil, s’acabaran tots els fils i es carregarà la nova imatge del procés i s’executarà. No hi ha funcions destructores que finalitzin els fils del procés actual.





El PID del procés no es modifica, sinó que es canvien les dades, el codi, la pila, la pila, etc. del procés i se substitueixen per les del procés recentment carregat. El nou procés s’executa des del punt d’entrada.

La trucada al sistema Exec és una col·lecció de funcions i, en llenguatge de programació C, els noms estàndard d’aquestes funcions són els següents:



  1. execl
  2. execle
  3. execlp
  4. execv
  5. executar
  6. execvp


Cal assenyalar aquí que aquestes funcions tenen la mateixa base exec seguit d'una o més lletres. A continuació, s’expliquen:

I: És un conjunt de punteres que apunta a variables d'entorn i es transmet explícitament al procés recentment carregat.

el: l és per als arguments de la línia d'ordres passada una llista a la funció

p: p és la variable d'entorn de camí d'accés que ajuda a trobar el fitxer passat com a argument per carregar-lo al procés.

v: v és per als arguments de la línia d'ordres. Aquests es passen com una matriu de punteres a la funció.

Per què s'utilitza exec?

exec s’utilitza quan l’usuari vol iniciar un fitxer o programa nou en el mateix procés.

Funcionament interior de l'exec

Penseu en els punts següents per entendre el funcionament de l'exec:

  1. La imatge de procés actual es sobreescriu amb una nova imatge de procés.
  2. La nova imatge de procés és la que heu passat com a argument exec
  3. S'ha finalitzat el procés en execució actual
  4. La nova imatge de procés té el mateix identificador de procés, el mateix entorn i el mateix descriptor de fitxers (perquè no se substitueix el procés, la imatge de procés es substitueix)
  5. L'estat de la CPU i la memòria virtual es veuen afectades. El mapatge de la memòria virtual de la imatge de procés actual se substitueix per la memòria virtual de la nova imatge de procés.

Sintaxis de les funcions de la família exec:

A continuació es mostren les sintaxis de cada funció de exec:

int execl (const char * path, const char * arg, ...)
int execlp (fitxer const char *, const char * arg, ...)
int execle (const char * path, const char * arg, ..., char * const envp [])
int execv (const char * path, const char * argv [])
int execvp (fitxer const char *, const char * argv [])
int execvpe (const char * file, const char * argv [], char * const envp [])

Descripció:

El tipus de retorn d’aquestes funcions és Int. Quan la imatge del procés es reemplaça correctament, no es torna a la funció de trucada perquè el procés que la va cridar ja no s'està executant. Però si hi ha algun error, es retornarà -1. Si es produeix algun error, an errno està configurat.

A la sintaxi:

  1. Camí s'utilitza per especificar el nom complet del camí d'accés del fitxer que s'ha d'executar.
  1. enfadat és l’argument aprovat. En realitat, és el nom del fitxer que s'executarà en el procés. La majoria de les vegades el valor d’arg i path és el mateix.
  1. const char * arg a les funcions execl (), execlp () i execle () es considera arg0, arg1, arg2, ..., argn. Bàsicament és una llista d’indicadors de cadenes terminades nul·les. Aquí el primer argument apunta al nom del fitxer que s’executarà tal com es descriu al punt 2.
  1. envp és una matriu que conté indicadors que apunten a les variables d'entorn.
  1. dossier s'utilitza per especificar el nom del camí d'accés que identificarà el camí del fitxer d'imatge de procés nou.
  1. Les funcions de la trucada exec que acaben amb I s’utilitzen per canviar l’entorn de la nova imatge de procés. Aquestes funcions passen la llista de paràmetres d'entorn mitjançant l'argument envp . Aquest argument és un conjunt de caràcters que apunta a la cadena finalitzada nul·la i defineix la variable d'entorn.

Per utilitzar les funcions de la família exec, heu d'incloure el fitxer de capçalera següent al programa C:

#incloure

Exemple 1: utilitzar la trucada al sistema exec al programa C.

Penseu en el següent exemple en què hem utilitzat la trucada del sistema exec a la programació C a Linux, Ubuntu: Tenim dos fitxers c aquí example.c i hello.c:

exemple.c

CODI:

#incloure
#incloure
#incloure
intprincipal(intargc, char *argv[])
{
printf ('PID d'exemple.c =% d n',getpid());
char *args[] = {'Hola', 'C', 'Programació',NUL};
execv('./Hola',args);
printf ('Torna a example.c');
tornar 0;
}

hola.c

CODI:

#incloure
#incloure
#incloure
intprincipal(intargc, char *argv[])
{
printf ('Estem a Hello.c n');
printf ('PID de hola.c =% d n',getpid());
tornar 0;
}

SORTIDA:

PID d'exemple.c = 4733
Estem a Hello.c
PID de hola.c = 4733

A l'exemple anterior tenim un fitxer example.c i un fitxer hello.c. En primer lloc, a l’exemple .c, hem imprès l’identificador del procés actual (el fitxer example.c s’executa en el procés actual). A continuació, a la següent línia hem creat una sèrie de punteres de caràcters. L'últim element d'aquesta matriu ha de ser NULL com a punt final.

A continuació, hem utilitzat la funció execv () que pren el nom del fitxer i la matriu de punter de caràcters com a argument. Aquí s'ha de tenir en compte que hem utilitzat ./ amb el nom del fitxer, especifica la ruta del fitxer. Com que el fitxer es troba a la carpeta on resideix example.c, no cal especificar el camí complet.

Quan es crida la funció execv (), la nostra imatge de procés se substituirà ara el fitxer example.c no està en procés, però el fitxer hello.c està en procés. Es pot veure que l’identificador de procés és el mateix tant si hello.c és una imatge de procés com exemple.c és una imatge de procés perquè el procés és el mateix i la imatge de procés només es reemplaça.

Aleshores, tenim aquí una altra cosa a destacar, que és la sentència printf () després que execv () no s’executi. Això es deu al fet que el control mai no es torna a la imatge de procés anterior un cop la substitueix la nova imatge de procés. El control només torna a la funció de trucada quan no es pot substituir la imatge del procés. (El valor de retorn és -1 en aquest cas).

Diferència entre les trucades al sistema fork () i exec ():

La trucada del sistema fork () s'utilitza per crear una còpia exacta d'un procés en execució i la còpia creada és el procés fill i el procés en execució és el procés pare. Mentre que, exec () la trucada al sistema s'utilitza per substituir una imatge de procés per una nova imatge de procés. Per tant, no hi ha cap concepte de processos pare i fill en la trucada al sistema exec ().

A la trucada del sistema fork (), els processos pare i fill s’executen al mateix temps. Però en la trucada al sistema exec (), si la substitució de la imatge del procés té èxit, el control no torna a on es va cridar la funció exec, sinó que executarà el nou procés. El control només es transferirà si hi ha algun error.

Exemple 2: Combinació de trucades al sistema fork () i exec ()

Penseu en el següent exemple en què hem utilitzat les trucades de sistema fork () i exec () al mateix programa:

exemple.c

CODI:

#incloure
#incloure
#incloure
intprincipal(intargc, char *argv[])
{
printf ('PID d'exemple.c =% d n',getpid());
pid_t pàg;
pàg=forquilla();
si(pàg== -1)
{
printf ('Hi ha un error en trucar a fork ()');
}
si(pàg==0)
{
printf ('Estem en procés infantil n');
printf ('Cridant hello.c des del procés fill n');
char *args[] = {'Hola', 'C', 'Programació',NUL};
execv('./Hola',args);
}
en cas contrari
{
printf ('Estem en el procés principal');
}
tornar 0;
}

hola.c:

CODI:

#incloure
#incloure
#incloure
intprincipal(intargc, char *argv[])
{
printf ('Estem a Hello.c n');
printf ('PID de hola.c =% d n',getpid());
tornar 0;
}

SORTIDA:

PID d'exemple.c = 4790
Estem en procés principal
Estem en procés infantil
S'està trucant a hello.c des del procés fill
Estem a hello.c
PID de hello.c = 4791

En aquest exemple hem utilitzat la trucada al sistema fork (). Quan es crea el procés fill, s'assignarà 0 a p i després passarem al procés fill. Ara s'executarà el bloc de sentències amb if (p == 0). Es mostra un missatge i hem utilitzat la trucada de sistema execv () i la imatge de procés fill actual que és example.c serà substituïda per hello.c. Abans de la trucada execv (), els processos fill i pare eren els mateixos.

Es pot veure que el PID de example.c i hello.c ara és diferent. Això es deu al fet que example.c és la imatge del procés principal i hello.c és la imatge del procés fill.