Exec (Unix): differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
FrescoBot (discussione | contributi)
m Bot: errori di battitura e modifiche minori
Olisait (discussione | contributi)
Funzionalità collegamenti suggeriti: 2 collegamenti inseriti.
 
(22 versioni intermedie di 11 utenti non mostrate)
Riga 1:
{{Titolo minuscolo}}
{{S|linguaggi di programmazione}}
{{F|linguaggi di programmazione|data=giugno 2007}}
 
'''Execexec''' è una [[Funzione (informatica)|funzione]] di sistema presente nella [[libreria standard del C]] del [[GNU|progetto GNU]], la [[GNU C Library]].
 
== Informazioni di carattere generale ==
 
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.
 
Riga 19 ⟶ 18:
Principalmente troviamo:
 
:<code>int execl(const char *pathpathname, const char *arg0arg, ..., (char *) NULL);</code>
:<code>int execle(const char *pathpathname, const char *arg0arg, ..., const(char *) NULL, char *const *envp[]);</code>
:<code>int execlp(const char *pathfile, const char *arg0arg, ..., (char *) NULL);</code>
:<code>int execlpe(const char *path, const char *arg0, ..., const char *const *envp); //Solo process.h ??</code>
:<code>int execv(const char *pathpathname, const char *const *argv[]);</code>
:<code>int execve(const char *pathpathname, const char *const *argv[], const char *const *envp[]);</code>
:<code>int execvp(const char *pathfile, const char *const *argv[]);</code>
:<code>int execvpe(const char *pathfile, const char *const *argv[], const char *const *envp[]);</code>
 
Il primo argomento, pathpathname che vediamo in ciascuno degli exec*, specifica il pathnamepercorso 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 nomi ===
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:
 
<syntaxhighlight lang="c">
execl("/bin/ls","ls", "-l", (char *)0);
execl("/bin/ls","ls", "-l", (char *)0);
</syntaxhighlight>
 
e il suo complementare che contiene la p ma non il path:
 
<syntaxhighlight lang="c">
execlp("ls","ls", "-l", (char *)0);
execlp("ls","ls", "-l", (char *)0);
</syntaxhighlight>
 
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:
Riga 53 ⟶ 55:
|<code>p</code>|| Non serve specificare il path.
|-
|<code>v</code>|| Gli argomenti a riga di comando saranno passati alla funzione tramite un array di puntatori.
|-
|<code>e</code>|| L'insieme dei puntatori dell'environment è passato esplicitamente al processo figlio.
Riga 70 ⟶ 72:
| <code>E2BIG</code>||Sono stati immessi troppi argomenti.
|-
| <code>EACCES</code>||Non si puo'può avere l'accesso al file specificato (problemi di blocco/privilegi).
|-
|<code>ENOENT</code>||Il file o il path specificato non esiste.
Riga 77 ⟶ 79:
|-
|}
 
 
Specifiche di Execve e delle sue varianti:
Riga 83 ⟶ 84:
=== execve ===
==== Sintassi ====
''int execve (const char *pathname, char *const argv[], char *const envp[])''
 
* "pathname" è il nome dell'eseguibile (completo di percorso) per il nuovo processo
''int execve (const char *filename, const char *argv[], const char *env[])''
* "argv[]" è il vettore degli argomenti in input a pathname (accessibile dal main come main(int argc, char *argv[], char *env[])).
 
* "env[]" è il vettore di ambiente in cui ''pathname'' è eseguito (accessibile dal main come main(int argc, char *argv[], char *env[])).
* filename è il nome dell'eseguibile per il nuovo processo
* Gli elementi di env hanno la forma "var=valore".
* 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 ====
 
execve esegue le seguenti azioni
* cerca il formato di filenamepathname
* lancia il loader per il formato di filenamepathname
* crea una nuova mappa di memoria per il processo
* sistema in maniera opportuna argomenti e ambiente
Riga 101:
* 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 ====
 
<syntaxhighlight lang="c">
/*file sorgente execve.c*/
 
#include <stdio.h>
/*file sorgente execve.c*/
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
extern char **environ;
int main() {
char *argv[]={"nomeFile", NULL};
if(execve("nomeFile", argv, enviroment))==-1)
perror("execve fallita");
}
 
extern char **environ;
=== execl ===
 
int main() {
==== esempio ====
char *argv[] = {"nomeFile", NULL};
 
if(execve("nomeFile", argv, enviroment))==-1)
perror("execve fallita");
 
}
</syntaxhighlight>
 
=== execl ===
==== esempio ====
Passiamo a visualizzare un esempio di utilizzo di execl:
 
<syntaxhighlight lang="c">
int main(){
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);
}
</syntaxhighlight>
 
''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 ===
 
==== esempio ====
 
Ora vediamo un esempio di utilizzo di execv:
 
<syntaxhighlight lang="c">
int main(){
int main() {
char *a[]={"ls","-l",(char *)0};
char *a[] = {"ls", "-l", (char *)0};
printf("Esecuzione di ls\n");
execv printf("/home/Esecuzione di ls\n",a);
execv("/home/ls", a);
 
printf("Si e' verificato un errore nell'esecuzione del codice\n");
printf("Si è verificato un errore nell'esecuzione del codice\n");
exit(1);
exit(1);
}
}
</syntaxhighlight>
 
''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 ===
Prototipo: <code>int execlp(const char *file, const char *arg, ..., (char *) NULL);</code>
 
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
Riga 164 ⟶ 162:
Esempio di utilizzo:
 
<syntaxhighlight lang="c">
for(i=1;i<=2;i++){
for (i=1; i<=2; i++){
fork();
fork();
execlp("echo", "myEcho", "i", (char*)0);
printf("%d\n", i); //codice che non verrà mai eseguito, a meno di errori nella execlp
}
}
</syntaxhighlight>
 
La compilazione fornirà in output:
i
Riga 175 ⟶ 174:
 
=== execvp ===
Prototipo: <code>int execvp(const char *file, char *const argv[]);</code>
{{...}}
 
Esempio di utilizzo:
 
<syntaxhighlight lang="c">
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);
}
</syntaxhighlight>
 
=== execle ===
{{...|informatica}}
 
== Collegamenti esterni ==
* {{Collegamenti esterni|OpenBsd man=https://man.openbsd.org/OpenBSD-6.7/amd64/execle.3}}
 
{{Portale|informatica}}