Exec (Unix)

Da Wikipedia, l'enciclopedia libera.

Exec è una funzione di sistema presente nella libreria standard del C del progetto GNU, la GNU C Library.

Informazioni di carattere generale[modifica | modifica sorgente]

Exec sostituisce i segmenti codice e dati del processo correntemente in esecuzione nello stato di utente con quelli di un altro programma contenuto in un file eseguibile specificato.

Agendo solo su processi in stato di utente la exec non interviene sul segmento di sistema e sui file utilizzati dal processo che la invoca.

Durante la chiamata ad exec e al successivo caricamento nella Ram del nuovo codice compilato il processo mantiene lo stesso pid.

La funzione exec deve passare dei parametri al nuovo programma che viene eseguito. Essi vengono letti dal programma tramite il meccanismo di passaggio usuale argc, argv.

Implementazione[modifica | modifica sorgente]

Questo servizio è implementato in C sotto Unix (ma anche in generale in POSIX ), tramite una famiglia di chiamate di sistema (comprese in unistd.h su unix e process.h nei sistemi dos/win32.).

Principalmente troviamo:

int execl(const char *path, const char *arg0, ...);
int execle(const char *path, const char *arg0, ..., const char *const *envp);
int execlp(const char *path, const char *arg0, ...);
int execlpe(const char *path, const char *arg0, ..., const char *const *envp);
int execv(const char *path, const char *const *argv);
int execve(const char *path, const char *const *argv, const char *const *envp);
int execvp(const char *path, const char *const *argv);
int execvpe(const char *path, const char *const *argv, const char *const *envp);

Il primo argomento, path che vediamo in ciascuno degli exec*, specifica il pathname del file da eseguire come processo figlio. Gli argomenti arg0,...,argN sono una lista di puntatori agli argomenti da passare al processo figlio; argv è un array di puntatori agli argomenti. L'argomento envp è invece un array di puntatori alla configurazione dell'ambiente attuale. Le chiamate execle, execlpe, execve ed execvpe (ovvero quelle con il suffisso 'e'), alterano l'ambiente del loro processo figlio, passando una lista con le configurazioni d'ambiente per l'appunto tramite l'argomento envp (array di puntatori a caratteri).

Funzioni e nomi[modifica | modifica sorgente]

L'unica vera chiamata di sistema è la execve, le altre si differenziano da questa per come vengono passati i parametri.

In linea di massima si può dire che la p finale che troviamo nelle due varianti execlp ed execvp, hanno come significato che il primo parametro passato come argomento non dev'essere necessariamente il path ma può essere il nome di ciò che intendiamo eseguire.


Un esempio potrebbe essere il seguente:

execl("/bin/ls","ls", "-l", (char *)0);

e il suo complementare che contiene la p ma non il path:

execlp("ls","ls", "-l", (char *)0);

Le altre lettere che possiamo trovare oltre al suffisso "p" (e, l o v) presentano dei significati ben precisi.

Riassumendo si hanno le seguenti funzioni di base:

Funzione Caratteristica
p Non serve specificare il path.
v Gli argomenti a riga di comando saranno passati alla funzione tramite un array di puntatori.
e L'insieme dei puntatori dell'environment è passato esplicitamente al processo figlio.
l Gli argomenti a riga di comando sono passati individualmente alla funzione.

Gestione degli errori[modifica | modifica sorgente]

Normalmente le funzioni exec* non tornano al processo chiamante, se una funzione exec torna al processo chiamate vuol dire che la chiamata non è andata a buon fine. Viene allora tornato il valore di errore -1, ed errno ci presenta uno dei seguenti valori:

Errore Significato
E2BIG Sono stati immessi troppi argomenti.
EACCES Non si può avere l'accesso al file specificato (problemi di blocco/privilegi).
ENOENT Il file o il path specificato non esiste.
ENOMEM Non c'è abbastanza memoria per eseguire il processo figlio


Specifiche di Execve e delle sue varianti:

execve[modifica | modifica sorgente]

Sintassi[modifica | modifica sorgente]

int execve (const char *filename, const char *argv[], const char *env[])

  • filename è il nome dell'eseguibile per il nuovo processo
  • argv è il vettore degli argomenti in input a filename (accessibile dal main come main(int argc, char * argv[], char*env[])).
  • env è il vettore di ambiente in cui filename è eseguito (accessibile dal main come main(int argc, char *argv[], char * env[])). Gli elementi di env hanno la forma "var=valore".

Comportamento[modifica | modifica sorgente]

execve esegue le seguenti azioni

  • cerca il formato di filename
  • lancia il loader per il formato di filename
  • crea una nuova mappa di memoria per il processo
  • sistema in maniera opportuna argomenti e ambiente
  • risistema le strutture dati di gestione della memoria del processo
  • carica una piccola parte dell'eseguibile (demand paging)
  • trasferisce il controllo al nuovo programma

Il processo viene poi messo in user mode: la chiamata - come tutte quelle della famiglia exec - non ritorna che in caso di errore.

Esempio d'uso[modifica | modifica sorgente]

/*file sorgente execve.c*/

#include <stdio.h>
#include <unistd.h>

extern char **environ;

int main() {
char *argv[]={"nomeFile", NULL};

if(execve("nomeFile", argv, enviroment))==-1)

perror("execve fallita");

}

execl[modifica | modifica sorgente]

esempio[modifica | modifica sorgente]

Passiamo a visualizzare un esempio di utilizzo di execl:

int main(){

printf("Esecuzione di ls\n");
execl("/bin/ls","ls","-l",(char*)0);

printf("Si e' verificato un errore nell'esecuzione del codice\n");
exit(1);
}

Osservazioni: Ci si potrebbe chiedere come mai dopo execl, ci sia una printf che segnala un errore, ed un'uscita che richiama un po' l'attenzione, ma bisogna pensare che execl elimina il programma originale sovrascrivendolo con quello passato come parametro. Quindi le istruzioni che seguono la chiamata ad execl, verranno eseguite solo se non sono state sovrascritte dal nuovo programma, cioè solo se si è verificato un errore durante l'esecuzione, e il controllo è stato ripassato al chiamante (execl).

execv[modifica | modifica sorgente]

esempio[modifica | modifica sorgente]

Ora vediamo un esempio di utilizzo di execv:

int main(){
char *a[]={"ls","-l",(char *)0};
printf("Esecuzione di ls\n");
execv("/home/ls",a);

printf("Si e' verificato un errore nell'esecuzione del codice\n");
exit(1);
}

Osservazioni: Come prima le istruzioni che seguono la chiamata ad execv, verranno eseguite solo se non sono state sovrascritte dal nuovo programma, cioè solo se si è verificato un errore durante l'esecuzione, e il controllo è stato ripassato al chiamante (execv).

execlp[modifica | modifica sorgente]

Prototipo: int execlp(const char *path, const char *arg0, ...)

  • Il primo argomento specifica il path del programma (cercato nelle cartelle della variabile di ambiente path)
  • Gli argomenti successivi, specificano una lista di stringhe terminata dalla stringa NULL che costituiscono gli argomenti passati al programma

Esempio di utilizzo:

 for(i=1;i<=2;i++){
       fork();
       execlp("echo","myEcho","i",(char*)0);
       printf("%d\n",i); //codice che non verrà mai eseguito, a meno di errori nella execlp
       } 

La compilazione fornirà in output:

i
i

execvp[modifica | modifica sorgente]

execle[modifica | modifica sorgente]

informatica Portale Informatica: accedi alle voci di Wikipedia che trattano di informatica