Laboratoire 4 - fork et exec

Page content

L’objectif de ce laboratoire est de se familiariser avec l’utilisation des appels système fork et exec

Mise en bouche

Écrire un programme fork0 effectuant les opérations suivantes, dans l’ordre :

  • Afficher « Mon PID est <pid>! ». Pour obtenir le PID, utiliser getpid().
  • Appeler la fonction fork().
  • Afficher « Je suis le <père|fils> et mon PID est <pid>. »

Voici un exemple de résultat:

Mon PID est <22097>
Je suis le père et mon PID est <22097>
Je suis le fils et mon PID est <22098>

Multiple fils

  • Écrire un programme famille qui crée 10 processus fils. Chacun d’entre eux devra afficher « Je suis le numéro <1 à 10>, mon PID est <pid> et mon père est <pid>! ».

  • Reprendre le programme famille et modifiez-le de façon à ce que le processus père, après avoir lancé les 10 fils, attende une entrée de l’utilisateur. Utilisez la fonction getchar(). À l’aide de la commande ps -a, exécutée dans une autre fenêtre-terminal, listez vos processus : pourquoi les 10 fils sont-ils encore là, bien que leur exécution soit terminée ? S’agit-il de processus zombies ?

  • Utiliser l’appel système waitpid() pour corriger le problème de la question précédente. Utiliser le man pour plus d’informations sur l’utilisation de cet appel système. Pour chaque processus fils terminant son exécution, dans le code du parent afficher « le processus No.<x>, PID <y> vient de terminer ».

Hiérarchie de processus

  • Créer une version pchaine du programme précédent qui réalise une chaine de n processus, où le nombre n est fourni par l’utilisateur à l’exécution de la commande. Chacun des processus devra afficher « Je suis un fils, mon PID est <pid> et mon père est <pid> ». Par chaine de processus, on entend un processus parent qui lance n enfants.

Exemple (les PID peuvent varier entre chaque exécution du programme):

$ pchaine 2
Je suis le père, mon PID est <31393>
	Je suis un fils, mon PID est <31394> et mon père est <31393>
	Je suis un fils, mon PID est <31395> et mon père est <31393>
  • Créer un programme parbre qui réalise un arbre de n processus. Chacun des processus devra afficher « Je suis un fils, mon PID est <pid> et mon père est <pid> ».
$ parbre 2
Je suis le père, mon PID est <31396>
	Je suis un fils, mon PID est <31397> et mon père est <31396>
		Je suis un fils, mon PID est <31398> et mon père est <31397>

Programme mystère

Soit le programme mystere.c suivant:

#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>

int main(void) {
    // ICI
    if (fork()*fork()) fork();
    else fork() || fork();
    // LÀ
    return 0;
}
  • Combien de processus sont créés ?

  • Dessinez la hiérarchie des processus.

  • Modifiez le programme « LÀ » pour que chaque processus affiche qui il est et quel est son parent. (comparez avec les questions précédentes).

    Attention à ce que vos parents affichés soient légitimes :)

  • Modifiez le programme « ICI » et « LÀ » de façon à ce que le programme affiche la hiérarchie des processus dans un format compatible avec graphviz. De façon à ce que : ./mystere | xdot - fonctionne.

Note : pas besoin d’être sophistiqué, la sortie suivante est très acceptable:

digraph {
rankdir = BT
1898331 -> 1898328
1898328 -> 1898327
1898327 -> 1486829
}

Recouvrement

  • Fonctions utiles: getenv, strtok

  • Exécuter la commande exec ps dans un terminal. Que se passe-t-il et pourquoi ? Vérifier votre explication avec l’utilisation de exec sh et de la commande ps.

  • Écrire un programme exec0 qui permet d’exécuter une commande qui lui est passée en argument. Exemple exec0 ps. Pour ce faire, utiliser la fonction execlp.

  • Reprendre le programme exec0 et remplacer l’utilisation de execlp par execvp afin d’exécuter la commande avec des arguments. Exemple exec0 ps -l

  • Reprendre le programme exec0 pour qu’une fois l’exécution de la commande terminée, le programme affiche “L’exécution de la commande est terminée”.

  • Bonus Reprendre le programme exec0 et remplacer l’utilisation de execvp par execv. Pour que cela fonctionne il est nécessaire de trouver le chemin du programme que l’utilisateur a fourni en argument. Utiliser la variable d’environnement PATH qui contient l’ensemble des répertoires où rechercher des programmes exécutables (la fonction getenv vous sera utile).

  • Bonus Écrire un programme exec5 qui se recouvre exactement 5 fois, en affichant “Je suis le recouvrement <numéro de recouvrement>.”. Vous devez utiliser uniquement les fonctions exec (execl, execlp, execle …).