Chiamata di sistema Exec Linux

Chiamata di sistema Exec Linux
La chiamata di sistema Exec viene utilizzata per eseguire un file che risiede in un processo attivo. Quando il exec viene chiamato il file eseguibile precedente viene sostituito e viene eseguito il nuovo file.

Più precisamente, possiamo dire che l'utilizzo della chiamata di sistema Exec sostituirà il vecchio file o il programma dal processo con un nuovo file o programma. L'intero contenuto del processo viene sostituito con un nuovo programma.

Il segmento di dati utente che esegue la chiamata di sistema EXEC () viene sostituito con il file di dati il ​​cui nome è fornito nell'argomento mentre si chiama Exec ().

Il nuovo programma viene caricato nello stesso spazio di processo. L'attuale processo viene appena trasformato in un nuovo processo e quindi il PID ID del processo non viene modificato, questo è perché non stiamo creando un nuovo processo, stiamo solo sostituendo un processo con un altro processo in Exec.

Se il processo attualmente in esecuzione contiene più di un thread, tutti i thread verranno terminati e la nuova immagine di processo verrà caricata e quindi eseguita. Non ci sono funzioni distruttive che terminano i thread del processo corrente.

PID del processo non viene modificato ma i dati, il codice, lo stack, l'heap, ecc. del processo viene modificato e sostituito da quelli del processo appena caricato. Il nuovo processo viene eseguito dal punto di ingresso.

Exec System Call è una raccolta di funzioni e in linguaggio di programmazione C, i nomi standard per queste funzioni sono i seguenti:

  1. Execl
  2. esecuzione
  3. Execlp
  4. Execv
  5. Execve
  6. Execvp


Va notato qui che queste funzioni hanno la stessa base Exec seguito da una o più lettere. Questi sono spiegati di seguito:

E: È una serie di puntatori che indica le variabili di ambiente e viene trasmessa esplicitamente al processo appena caricato.

L: L è per gli argomenti della riga di comando passati a un elenco alla funzione

P: P è la variabile per l'ambiente del percorso che aiuta a trovare il file passato come argomento da caricare in processo.

V: V è per gli argomenti della riga di comando. Questi vengono passati come una matrice di puntatori alla funzione.

Perché il dirigente viene utilizzato?

Exec viene utilizzato quando l'utente desidera avviare un nuovo file o un programma nello stesso processo.

Lavoro interiore del dirigente

Considera i seguenti punti per capire il funzionamento del dirigente:

  1. L'immagine di processo corrente è sovrascritta con una nuova immagine di processo.
  2. La nuova immagine di processo è quella che hai superato come argomento esecutivo
  3. Il processo attualmente in esecuzione è terminato
  4. La nuova immagine di processo ha lo stesso ID di processo, lo stesso ambiente e lo stesso descrittore di file (perché il processo non viene sostituito l'immagine di processo viene sostituita)
  5. La statistica della CPU e la memoria virtuale sono interessate. La mappatura della memoria virtuale dell'immagine di processo corrente viene sostituita dalla memoria virtuale della nuova immagine di processo.

Sintassi delle funzioni della famiglia Exec:

Le seguenti sono le sintassi per ogni funzione di Exec:

int execl (const char* percorso, const char* arg,…)
int execlp (const char* file, const char* arg,…)
int execle (const char* percorso, const char* arg,…, char* const envp [])
int execv (const char* percorso, const char* argv [])
int execvp (file const char*, const char* argv [])
int execvpe (const char* file, const char* argv [], char* const envp [])

Descrizione:

Il tipo di ritorno di queste funzioni è int. Quando l'immagine del processo viene sostituita correttamente, nulla viene restituito alla funzione di chiamata perché il processo che la chiamava non è più in esecuzione. Ma se si restituisce un errore -1. Se si verifica un errore un errno è impostato.

Nella sintassi:

  1. sentiero viene utilizzato per specificare il nome completo del percorso del file che deve essere eseguito.
  1. arg è l'argomento approvato. In realtà è il nome del file che verrà eseguito nel processo. Il più delle volte il valore di Arg e percorso è lo stesso.
  1. const char* arg In funzioni esecutivi (), esecuzione () ed esecu () sono considerati arg0, arg1, arg2, ..., argn. È fondamentalmente un elenco di puntatori per le stringhe null terminate. Qui il primo argomento indica il nome file che verrà eseguito come descritto nel punto 2.
  1. envp è un array che contiene puntatori che indicano le variabili di ambiente.
  1. file viene utilizzato per specificare il nome del percorso che identificherà il percorso del nuovo file di immagine di processo.
  1. Le funzioni del dirigente chiamate finali con e vengono utilizzati per cambiare l'ambiente per la nuova immagine di processo. Queste funzioni passano l'elenco dell'ambiente utilizzando l'argomento envp. Questo argomento è una matrice di caratteri che indica la stringa terminata null e definisce la variabile di ambiente.

Per utilizzare le funzioni della famiglia Exec, è necessario includere il seguente file di intestazione nel programma C:

#includere

Esempio 1: Utilizzo della chiamata del sistema Exec in programma C

Considera il seguente esempio in cui abbiamo usato la chiamata del sistema Exec in C di programmazione in Linux, Ubuntu: abbiamo due file C qui Esempio.c e ciao.C:

esempio.C

CODICE:

#includere
#includere
#includere
int main (int argc, char *argv [])

printf ("pid dell'esempio.c = %d \ n ", getpid ());
char *args [] = "ciao", "c", "programmazione", null;
Execv ("./ciao ", args);
printf ("torna all'esempio.C");
restituzione 0;

Ciao.C

CODICE:

#includere
#includere
#includere
int main (int argc, char *argv [])

printf ("Siamo in ciao.c \ n ");
printf ("Pid of Hello.c = %d \ n ", getpid ());
restituzione 0;

PRODUZIONE:

Pid di esempio.C = 4733
Siamo in ciao.C
Pid di Hello.C = 4733

Nell'esempio sopra abbiamo un esempio.File C e ciao.file c. Nell'esempio .c file prima di tutto abbiamo stampato l'ID del processo corrente (esempio di file.C è in esecuzione nel processo corrente). Quindi nella riga successiva abbiamo creato una serie di puntatori di personaggi. L'ultimo elemento di questo array dovrebbe essere nullo come punto di terminazione.

Quindi abbiamo usato la funzione execv () che prende il nome del file e l'array puntatore del personaggio come argomento. Va notato qui che abbiamo usato ./ Con il nome del file, specifica il percorso del file. Come file si trova nella cartella in cui esempio.C risiede, quindi non è necessario specificare l'intero percorso.

Quando viene chiamata la funzione Execv (), la nostra immagine di processo verrà sostituita ora l'esempio del file.C non è nel processo ma il file ciao.C è nel processo. Si può vedere che l'ID processo è lo stesso se ciao.C è l'immagine o l'esempio del processo.C è l'immagine di processo perché il processo è uguale e l'immagine di processo viene sostituita solo.

Quindi abbiamo un'altra cosa da notare qui che è l'istruzione printf () dopo il execv () non viene eseguita. Questo perché il controllo non viene mai restituito alla vecchia immagine di processo una volta che la nuova immagine di processo la sostituisce. Il controllo ritorna solo alla funzione di chiamata quando si sostituisce l'immagine del processo non ha successo. (Il valore di ritorno è -1 in questo caso).

Differenza tra le chiamate di sistema FORK () e Exec ():

La chiamata di sistema FORK () viene utilizzata per creare una copia esatta di un processo in esecuzione e la copia creata è il processo figlio e il processo in esecuzione è il processo genitore. Considerando che la chiamata di sistema Exec () viene utilizzata per sostituire un'immagine di processo con una nuova immagine di processo. Quindi non esiste un concetto di processi genitore e figlio nella chiamata di sistema Exec ().

Nel sistema FORK () Chiama i processi genitore e figlio vengono eseguiti contemporaneamente. Ma nella chiamata di sistema Exec (), se la sostituzione dell'immagine del processo ha esito positivo, il controllo non torna a dove è stata chiamata la funzione Exec piuttosto, eseguirà il nuovo processo. Il controllo verrà trasferito indietro solo in caso di errore.

Esempio 2: Combining FORK () e Exec () Chiamate di sistema

Considera il seguente esempio in cui abbiamo usato sia le chiamate di sistema FORK () che Exec () nello stesso programma:

esempio.C

CODICE:

#includere
#includere
#includere
int main (int argc, char *argv [])

printf ("pid dell'esempio.c = %d \ n ", getpid ());
pid_t p;
p = fork ();
if (p ==-1)

printf ("C'è un errore mentre si chiama fork ()");

if (p == 0)

printf ("Siamo nel processo figlio \ n");
printf ("Calling Hello.C dal processo figlio \ n ");
char *args [] = "ciao", "c", "programmazione", null;
Execv ("./ciao ", args);

altro

printf ("Siamo nel processo genitore");

restituzione 0;

Ciao.C:

CODICE:

#includere
#includere
#includere
int main (int argc, char *argv [])

printf ("Siamo in ciao.c \ n ");
printf ("Pid of Hello.c = %d \ n ", getpid ());
restituzione 0;

PRODUZIONE:

Pid di esempio.C = 4790
Siamo nel processo dei genitori
Siamo nel processo di figlio
Chiamando ciao.C dal processo del bambino
Siamo in ciao.C
Pid di Hello.c = 4791

In questo esempio abbiamo usato la chiamata di sistema FORK (). Quando il processo figlio viene creato 0 verrà assegnato a P e quindi passeremo al processo figlio. Ora verrà eseguito il blocco di dichiarazioni con if (p == 0). Viene visualizzato un messaggio e abbiamo usato la chiamata di sistema Execv () e l'immagine del processo figlio corrente che è Esempio.C sarà sostituito con ciao.C. Prima di Execv () Chiamare i processi figlio e genitore erano gli stessi.

Si può vedere che il PID dell'esempio.c e ciao.c è diverso ora. Questo perché esempio.C è l'immagine del processo genitore e ciao.C è l'immagine del processo del bambino.