Appel système Linux Exec

Linux Exec System Call



L'appel système exec est utilisé pour exécuter un fichier qui réside dans un processus actif. Lorsque exec est appelé, le fichier exécutable précédent est remplacé et le nouveau fichier est exécuté.

Plus précisément, nous pouvons dire que l'utilisation de l'appel système exec remplacera l'ancien fichier ou programme du processus par un nouveau fichier ou programme. L'ensemble du contenu du processus est remplacé par un nouveau programme.







Le segment de données utilisateur qui exécute l'appel système exec() est remplacé par le fichier de données dont le nom est fourni dans l'argument lors de l'appel à exec().



Le nouveau programme est chargé dans le même espace de processus. Le processus actuel est simplement transformé en un nouveau processus et, par conséquent, l'ID de processus PID n'est pas modifié, car nous ne créons pas de nouveau processus, nous remplaçons simplement un processus par un autre processus dans exec.



Si le processus en cours d'exécution contient plus d'un thread, tous les threads seront terminés et la nouvelle image de processus sera chargée puis exécutée. Il n'y a pas de fonctions destructrices qui terminent les threads du processus en cours.





Le PID du processus n'est pas modifié mais les données, le code, la pile, le tas, etc. du processus sont modifiés et remplacés par ceux du processus nouvellement chargé. Le nouveau processus est exécuté à partir du point d'entrée.

L'appel système Exec est un ensemble de fonctions et en langage de programmation C, les noms standard de ces fonctions sont les suivants :



  1. execl
  2. exécuter
  3. à l'exception
  4. execv
  5. executif
  6. execvp


Il est à noter ici que ces fonctions ont la même base l'exécutif suivi d'une ou plusieurs lettres. Ceux-ci sont expliqués ci-dessous :

Et: C'est un tableau de pointeurs qui pointe vers des variables d'environnement et est passé explicitement au processus nouvellement chargé.

l: l est pour les arguments de ligne de commande passés une liste à la fonction

p : p est la variable d'environnement du chemin qui aide à trouver le fichier passé en argument à charger dans le processus.

v : v est pour les arguments de ligne de commande. Ceux-ci sont passés sous forme de tableau de pointeurs vers la fonction.

Pourquoi exec est-il utilisé ?

exec est utilisé lorsque l'utilisateur souhaite lancer un nouveau fichier ou programme dans le même processus.

Fonctionnement interne de l'exécutif

Considérez les points suivants pour comprendre le fonctionnement d'exec :

  1. La mémoire image actuelle est écrasée par une nouvelle mémoire image.
  2. La nouvelle image de processus est celle que vous avez passée comme argument exec
  3. Le processus en cours est terminé
  4. La nouvelle image de processus a le même ID de processus, le même environnement et le même descripteur de fichier (car le processus n'est pas remplacé, l'image de processus est remplacée)
  5. La statistique du processeur et la mémoire virtuelle sont affectées. Le mappage de la mémoire virtuelle de l'image de processus actuelle est remplacé par la mémoire virtuelle de la nouvelle image de processus.

Syntaxes des fonctions de la famille exec :

Voici les syntaxes pour chaque fonction de exec :

int execl(const char* chemin, const char* argument, …)
int execlp(fichier const char*, const char* arg, …)
int execle(const char* chemin, const char* arg, …, char* const envp[])
int execv(const char* chemin, const char* argv[])
int execvp(fichier const char*, const char* argv[])
int execvpe(fichier const char*, const char* argv[], char *const envp[])

La description:

Le type de retour de ces fonctions est Int. Lorsque l'image de processus est remplacée avec succès, rien n'est renvoyé à la fonction appelante car le processus qui l'a appelée n'est plus en cours d'exécution. Mais s'il y a une erreur, -1 sera renvoyé. Si une erreur se produit, un errno est réglé.

Dans la syntaxe :

  1. chemin est utilisé pour spécifier le nom de chemin complet du fichier qui doit être exécuté.
  1. en colère est l'argument passé. C'est en fait le nom du fichier qui sera exécuté dans le processus. La plupart du temps, la valeur de arg et path est la même.
  1. const car* argument dans les fonctions execl(), execlp() et execle() est considéré comme arg0, arg1, arg2, …, argn. Il s'agit essentiellement d'une liste de pointeurs vers des chaînes terminées par NULL. Ici, le premier argument pointe vers le nom de fichier qui sera exécuté comme décrit au point 2.
  1. envp est un tableau qui contient des pointeurs qui pointent vers les variables d'environnement.
  1. déposer est utilisé pour spécifier le nom de chemin qui identifiera le chemin du nouveau fichier image de processus.
  1. Les fonctions d'appel exec qui se terminent par Et sont utilisés pour modifier l'environnement de la nouvelle image de processus. Ces fonctions passent la liste des paramètres d'environnement en utilisant l'argument envp . Cet argument est un tableau de caractères qui pointe vers une chaîne terminée par null et définit la variable d'environnement.

Pour utiliser les fonctions de la famille exec, vous devez inclure le fichier d'en-tête suivant dans votre programme C :

#comprendre

Exemple 1 : Utilisation de l'appel système exec dans le programme C

Considérons l'exemple suivant dans lequel nous avons utilisé l'appel système exec dans la programmation C sous Linux, Ubuntu : Nous avons ici deux fichiers c example.c et hello.c :

exemple.c

CODE:

#comprendre
#comprendre
#comprendre
entierprincipale(entierargc, carboniser *argv[])
{
imprimer ('PID de l'exemple.c = %d ',getpid());
carboniser *arguments[] = {'Bonjour', 'C', 'La programmation',NUL};
execv('./Bonjour',arguments);
imprimer ('Retour à exemple.c');
revenir 0;
}

Bonjour c

CODE:

#comprendre
#comprendre
#comprendre
entierprincipale(entierargc, carboniser *argv[])
{
imprimer ('Nous sommes dans Hello.c ');
imprimer ('PID de bonjour.c = %d ',getpid());
revenir 0;
}

SORTIR:

PID de l'exemple.c = 4733
Nous sommes dans Hello.c
PID de bonjour.c = 4733

Dans l'exemple ci-dessus, nous avons un fichier example.c et un fichier hello.c. Dans l'exemple de fichier .c, nous avons tout d'abord imprimé l'ID du processus en cours (le fichier exemple.c est en cours d'exécution dans le processus en cours). Ensuite, dans la ligne suivante, nous avons créé un tableau de pointeurs de caractères. Le dernier élément de ce tableau doit être NULL comme point de terminaison.

Ensuite, nous avons utilisé la fonction execv() qui prend le nom du fichier et le tableau de pointeurs de caractères comme argument. Il est à noter ici que nous avons utilisé ./ avec le nom de fichier, il précise le chemin du fichier. Comme le fichier se trouve dans le dossier où réside example.c, il n'est donc pas nécessaire de spécifier le chemin complet.

Lorsque la fonction execv() est appelée, notre image de processus sera remplacée maintenant le fichier example.c n'est pas dans le processus mais le fichier hello.c est dans le processus. On peut voir que l'ID de processus est le même, que hello.c soit une image de processus ou exemple.c soit une image de processus, car le processus est le même et l'image de processus est uniquement remplacée.

Ensuite, nous avons une autre chose à noter ici qui est l'instruction printf () après que execv () n'est pas exécuté. En effet, le contrôle n'est jamais rendu à l'ancienne image de processus une fois que la nouvelle image de processus la remplace. La commande ne revient à appeler la fonction que lorsque le remplacement de l'image de process échoue. (La valeur de retour est -1 dans ce cas).

Différence entre les appels système fork() et exec() :

L'appel système fork() est utilisé pour créer une copie exacte d'un processus en cours d'exécution et la copie créée est le processus enfant et le processus en cours est le processus parent. Alors que l'appel système exec() est utilisé pour remplacer une image de processus par une nouvelle image de processus. Par conséquent, il n'y a pas de concept de processus parent et enfant dans l'appel système exec().

Dans l'appel système fork(), les processus parent et enfant sont exécutés en même temps. Mais dans l'appel système exec(), si le remplacement de l'image de processus réussit, le contrôle ne revient pas à l'endroit où la fonction exec a été appelée, il exécutera plutôt le nouveau processus. Le contrôle ne sera retransféré qu'en cas d'erreur.

Exemple 2 : Combiner les appels système fork() et exec()

Considérons l'exemple suivant dans lequel nous avons utilisé à la fois les appels système fork() et exec() dans le même programme :

exemple.c

CODE:

#comprendre
#comprendre
#comprendre
entierprincipale(entierargc, carboniser *argv[])
{
imprimer ('PID de l'exemple.c = %d ',getpid());
pid_t p;
p=fourchette();
si(p== -1)
{
imprimer ('Il y a une erreur lors de l'appel de fork()');
}
si(p==0)
{
imprimer ('Nous sommes dans le processus de l'enfant ');
imprimer ('Appel hello.c depuis le processus enfant ');
carboniser *arguments[] = {'Bonjour', 'C', 'La programmation',NUL};
execv('./Bonjour',arguments);
}
autre
{
imprimer (« Nous sommes dans le processus parental »);
}
revenir 0;
}

Bonjour c:

CODE:

#comprendre
#comprendre
#comprendre
entierprincipale(entierargc, carboniser *argv[])
{
imprimer ('Nous sommes dans Hello.c ');
imprimer ('PID de bonjour.c = %d ',getpid());
revenir 0;
}

SORTIR:

PID de l'exemple.c = 4790
Nous sommes dans le processus parental
Nous sommes en processus enfant
Appel de hello.c à partir du processus enfant
Nous sommes en bonjour.c
PID de bonjour.c = 4791

Dans cet exemple, nous avons utilisé l'appel système fork(). Lorsque le processus enfant est créé, 0 sera affecté à p, puis nous passerons au processus enfant. Maintenant, le bloc d'instructions avec if(p==0) sera exécuté. Un message s'affiche et nous avons utilisé l'appel système execv() et l'image de processus enfant actuelle qui est example.c sera remplacée par hello.c. Avant execv(), les processus enfants et parents étaient identiques.

On peut voir que le PID de example.c et hello.c est différent maintenant. En effet, example.c est l'image de processus parent et hello.c est l'image de processus enfant.