next up previous contents index return to home!
Next: Un esempio Up: Processi Previous: Terminazione dei processi   Indice   Indice analitico

Caricamento di un programma in memoria

Per evitare di dover scrivere il corpo dei due processi nello stesso file, Unix mette a disposizione la famiglia di funzioni exec().

Come detto, la primitiva fork() permette di creare un nuovo processo, copiando nel suo spazio di memoria lo spazio di memoria del processo creante, e questo obbliga a inserire il codice ed i dati di tutti i processi nello stesso eseguibile, con conseguente aumento delle dimensioni degli eseguibili, complicazione della struttura del programma e perdita di flessibilità.

Inoltre, si pone il problema di eseguire un processo esterno già esistente, scritto da un altro utente. Ad esempio, supponiamo di voler ottenere informazioni sui processi attualmente in esecuzione nel sistema. Un metodo abbastanza semplice potrebbe essere quello eseguire il programma ps, presente in tutte le distribuzioni UNIX. Questa operazione viene anche chiamata spawn: cioè si crea un processo che esegue un programma esterno.

Per permettere questo, Unix mette a disposizione la famiglia di funzioni exec(). Onguna delle funzione della famiglia, sebbene con modalità leggermente differenti si occupa di sovrascrivere i dati, il segmento BSS ed il codice di un processo con un'immagine prelevata da disco.

È da notare che una funzione della famiglia exec() non crea un nuovo processo, ma semplicemente modifica lo spazio di memoria del processo che la chiama; per questo motivo, in caso di corretto funzionamento la exec() non ritornerà. È quindi chiaro che se la syscall ritorna un valore al chiamante, tale valore è necessariamente minore di 0 (tipicamente -1). A livello intuitivo, una exec() è paragonabile ad una jmp nel codice di un altro file oggetto, che rimpiazza il primo nella memoria privata del processo.

La famiglia di funzioni exec è composta da execl(), execlp(), execle(), execv(), execvp() ed execve(); tipicamente, tutte tali funzioni sono basate sulla execve(), costituendo dei meri front-end verso di essa. Per questo motivo, in questa sede tratteremo solo la execve(), rimandando ai manfile (man exec) per la sintassi e la semantica delle altre syscall della famiglia.



#include<unistd.h>

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


Argomenti in ingresso :

filename
- Nome del file da caricare in memoria
argv
- Lista dei parametri
argv
- Lista delle variabili di ambiente.

Valore restituito :

-1
- In caso di errore
Non ritorna
- In caso di corretto funzionamento.

Carica in memoria l'eseguibile indicato dal parametro filename (nella directory corrente), passandogli come parametri la lista di stringhe indicata da argv, e creandogli un ambiente con definite le variabili specificate da envp.

Il parametro argv è un array di puntatori a stringhe, ognuna delle quali specifica un parametro passato al programma. L'ultimo elemento dell'array deve essere NULL (0). Per convenzione, il primo parametro deve sempre essere il nome dell'eseguibile.

Ecco quindi come usare la execve():

Esempio


next up previous contents index
Next: Un esempio Up: Processi Previous: Terminazione dei processi   Indice   Indice analitico
Giuseppe Lipari 2002-10-27