Exec (Unix)exec è una funzione di sistema presente nella libreria standard del C del progetto GNU, la GNU C Library. Informazioni di carattere generaleExec 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. ImplementazioneQuesto 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:
Il primo argomento, pathname che vediamo in ciascuno degli exec*, specifica il percorso e il nome 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 nomiL'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:
Gestione degli erroriNormalmente 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:
Specifiche di Execve e delle sue varianti: execveSintassiint execve (const char *pathname, char *const argv[], char *const envp[])
Comportamentoexecve esegue le seguenti azioni
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/*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");
}
execlesempioPassiamo a visualizzare un esempio di utilizzo di execl: int main(){
printf("Esecuzione di ls\n");
execl("/bin/ls", "ls", "-l", (char*)0);
printf("Si è 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). execvesempioOra 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 è 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). execlpPrototipo:
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 execvpPrototipo: Esempio di utilizzo: int main(){
char *a[]={"ls", "-l", (char *)0};
printf("Esecuzione di ls\n");
execvp("ls", a);
printf("Si è verificato un errore nell'esecuzione del codice\n");
exit(1);
}
execleCollegamenti esterni
|