Exercises on Process Management

Exercice 1 - Concept de processus Question 1 - Un processus est-il une entité produite après compilation ? Réponse : NON. Justification : La compilation d'un programme source (par exemple un code en C) produit un fichier binaire (un exécutable), qui est une entité statique stockée sur le disque dur. Un processus, en revanche, est par définition l'image d'un programme en cours d'exécution.

D'après le document Exercises on Process Management

Cet article a été rédigé automatiquement à partir du document source, puis vérifié avant publication.

Exercises on Process Management

Document source

Exercises on Process Management

Operating Systems, Process Management · PDF · 14 pages · 2018

Afficher l'aperçu du document

Consulter le document original →

Exercice 1 - Concept de processus

Question 1 - Un processus est-il une entité produite après compilation ?

Réponse : NON.

Justification : La compilation d'un programme source (par exemple un code en C) produit un fichier binaire (un exécutable), qui est une entité statique stockée sur le disque dur. Un processus, en revanche, est par définition l'image d'un programme en cours d'exécution. Il possède un état dynamique (un compteur de programme, des registres, un espace d'adressage en mémoire, etc.) que le simple fichier binaire ne possède pas.

Question 2 - Un processus est-il une entité produite après chargement d’un binaire en mémoire ?

Réponse : OUI.

Justification : Pour qu'un programme binaire s'exécute, le système d'exploitation doit le charger depuis le disque vers la mémoire principale (RAM). Une fois ce chargement effectué et les structures de contrôle allouées par le système d'exploitation, l'entité dynamique créée est prête à être ordonnancée par le processeur. C'est précisément cela, un processus.

Exercice 2 - Création de processus par appels système

Note de correction : Les portions de code fournies dans l'énoncé s'appuient sur la fonction fork(). Bien que non précisé dans le code source de l'examen, rappelons que pour compiler ce code correctement en langage C, il faudrait inclure la bibliothèque <unistd.h>.

Programme 1 - Séquence linéaire d'appels

int main() {
    fork();
    fork();
    fork();
}

Nombre de processus créés : 8

Explication de l'exécution : Chaque appel à la fonction fork() duplique le processus appelant, créant un processus enfant qui poursuivra son exécution exactement à l'instruction suivante.

  1. L'exécution initiale du programme démarre avec un processus unique : P1.
  2. Au premier fork(), P1 se duplique et crée P2. Nous avons maintenant 2 processus (P1 et P2) qui passent à la ligne suivante.
  3. Au second fork(), les 2 processus existants se dupliquent : P1 crée P3, et P2 crée P4. Nous avons maintenant 4 processus en cours d'exécution.
  4. Au troisième fork(), les 4 processus se dupliquent : P1 crée P5, P2 crée P6, P3 crée P7 et P4 crée P8.

Tous ces processus arrivent à la fin de la fonction main(). Le nombre total de processus est 2³ = 8.

Programme 2 - Appel conditionnel

int main() {
    if (fork() > 0)
        fork();
}

Nombre de processus créés : 3

Explication de l'exécution : La particularité de fork() est sa valeur de retour : elle renvoie le PID (un entier > 0) du nouveau processus au parent, et elle renvoie 0 au processus enfant.

  1. Le programme démarre avec le processus P1.
  2. L'instruction fork() dans la condition du if est exécutée. P1 se duplique et crée le processus enfant P2.
  3. Les deux processus évaluent ensuite la condition :
    • Pour le parent P1 : la valeur de retour est le PID de P2 (strictement supérieur à 0). La condition > 0 est vraie. P1 entre donc dans le bloc du if et exécute le second fork(). Il crée alors un troisième processus, P3.
    • Pour l'enfant P2 : la valeur de retour du premier appel est 0. La condition > 0 est fausse. P2 n'entre pas dans le bloc du if et n'exécute aucune autre instruction.
  4. Il n'y a plus d'instructions à exécuter. Au total, les processus P1, P2 et P3 ont été créés.

Programme 3 - Appels dans une boucle itérative

int main() {
    int cpt = 0;
    while (cpt < 3) {
        if (fork() > 0)
            cpt++;
        else
            cpt = 3;
    }
}

Nombre de processus créés : 4

Explication de l'exécution : Dans ce programme, il faut suivre attentivement la valeur de la variable cpt (compteur) car sa modification n'est pas la même dans les processus parents et enfants. L'espace mémoire étant dupliqué, chaque processus possède sa propre copie de la variable cpt.

  1. Départ : Le processus P1 démarre et initialise sa variable cpt à 0.
  2. Itération 1 (cpt = 0) : P1 entre dans la boucle while (0 < 3). Il exécute if (fork() > 0) et crée P2.
    • Pour P1 (parent) : le retour est > 0. Il exécute cpt++. La valeur de cpt pour P1 passe à 1.
    • Pour P2 (enfant) : le retour est 0. Il exécute le bloc else et force sa variable cpt à 3. Lors du prochain test de la boucle, la condition 3 < 3 sera fausse. P2 sort de la boucle et se termine.
  3. Itération 2 (cpt = 1 pour P1) : P1 continue dans la boucle while (1 < 3). Il exécute le if (fork() > 0) et crée P3.
    • Pour P1 (parent) : le retour est > 0. P1 exécute cpt++, sa variable passe à 2.
    • Pour P3 (enfant) : le retour est 0. Il exécute le bloc else, sa variable passe à 3. Il sortira de la boucle au test suivant.
  • Itération 3 (cpt = 2 pour P1) : P1 continue dans la boucle while (2 < 3). Il exécute le if (fork() > 0) et crée P4.
    • Pour P1 (parent) : le retour est > 0. P1 exécute cpt++, sa variable passe à 3.
    • Pour P4 (enfant) : le retour est 0. Il exécute le bloc else, sa variable passe à 3.
  • Fin : Au tour de boucle suivant, P1 évalue 3 < 3, ce qui est faux. P1 sort de la boucle.
  • Le processus parent P1 a engendré successivement P2, P3 et P4. Tous les processus ont quitté la boucle sans générer de nouveaux enfants. Total : 4 processus.

    Méthode

    Pour réussir les exercices de traçage de processus (comme ceux portant sur fork()), voici la démarche systématique à adopter :

    1. Dessiner un arbre généalogique : Ne tentez pas de compter mentalement. Sur votre brouillon, tracez un cercle pour P1. À chaque exécution de fork(), dessinez une nouvelle branche vers un nouveau cercle.
    2. Mémoriser la règle d'or de la valeur de retour : L'appel fork() est exécuté une seule fois, mais il retourne deux fois (une fois dans l'espace mémoire du parent, une fois dans celui de l'enfant). Notez bien sur chaque branche de votre arbre la valeur retournée : PID du fils (donc > 0) du côté du parent, et 0 du côté du fils.
    3. Tracer l'état mémoire de chaque nœud : Dès qu'un fork() a lieu, les variables (comme un compteur de boucle) sont copiées. Si le code modifie une variable dans une branche if/else, modifiez cette valeur uniquement pour le processus concerné dans votre arbre.
    4. Attention aux boucles et conditions : Vérifiez toujours si un processus enfant est autorisé à refaire un tour de boucle ou s'il rencontre un break, un exit(), ou une modification de variable qui le fait sortir de la logique d'itération (comme dans le Programme 3).

    Partager

    Commentaires

    Aucun commentaire pour le moment. Posez la première question.

    Les commentaires sont relus avant publication. Votre e-mail n'est jamais affiché.

    ← Toutes les révisions