Partie 4 - Processus

p4e1 - Premier fork

Écrivez un programme C qui :

  1. Affiche « Avant le fork, pid = PID »

  2. Crée un processus enfant avec fork()

  3. Le parent affiche : « Je suis le parent, PID = X, mon enfant a le PID = Y »

  4. L’enfant affiche : « Je suis l’enfant, PID = X, mon parent a le PID = Y » puis se termine avec _exit(0)

  5. Le parent attend l’enfant avec wait() et affiche le code de retour

Résultat attendu :

$ gcc -std=c2x -Wall -Wextra -pedantic -g p4e1.c -o p4e1 && ./p4e1
Avant le fork
Je suis le parent, PID = 12345, mon enfant a le PID = 12346
Je suis l'enfant, PID = 12346, mon parent a le PID = 12345
Parent: enfant terminé normalement, code retour = 0

p4e2 - Copy-on-Write et isolation mémoire

Créez un programme qui montre l’isolation mémoire entre processus :

  • Créez un entier x = 4

  • fork() un processus enfant

  • L’enfant modifie x = 2 et dort 2 secondes

  • Les deux affichent la valeur et l’adresse de x (avec %p)

Résultat attendu :

$ gcc -std=c2x -Wall -Wextra -pedantic -g p4e2.c -o p4e2 && ./p4e2
[parent] PID=12345              x=5  &x=0x7ffd055fdc60
[child]  PID=12346, PPID=12345  x=2  &x=0x7ffd055fdc60

Les adresses sont identiques mais les valeurs diffèrent. Pourquoi ?

p4e3 - Fork + Exec simple

Écrire un programme qui :

  • fork() un enfant

  • L’enfant exécute la commande cat -n p4e3.c (voir exec). Si exec échoue → perror("exec") puis ``_exit(1)``

  • Le parent attend avec waitpid() et affiche si l’enfant s’est bien terminé

Résultat attendu :

$ gcc -std=c2x -Wall -Wextra -pedantic -g p4e3.c -o p4e3 && ./p4e3
... contenu de p4e3.c ...
Parent: enfant terminé (OK)

p4e4 - Intercepter SIGINT (Ctrl+C)

Programmer un handler via sigaction avec SA_RESTART qui :

  • Enregistre le numéro du dernier signal dans volatile sig_atomic_t last_signal

  • Utilise un drapeau volatile sig_atomic_t stop = 0 pour arrêter la boucle

  • Boucle avec pause() jusqu’à réception de SIGINT

  • Affiche ensuite strsignal(last_signal)

Résultat attendu :

$ gcc -std=c2x -Wall -Wextra -pedantic -g p4e4.c -o p4e4 && ./p4e4
PID=12345. Appuyez sur Ctrl+C pour envoyer SIGINT.
^C
Signal reçu : 2 (Interrupt)

Testez le programme en envoyant un signal avec la commande kill depuis un autre terminal.

p4e5 - Pipe unidirectionnel parent→enfant

Écrire un programme qui :

  • Crée un pipe(fd)

  • fork() un enfant

  • Le parent écrit un message dans fd[1], puis ferme fd[1]

  • L’enfant lit depuis fd[0] et affiche, puis ferme fd[0]

  • Bien fermer les extrémités inutiles dans chaque processus

Résultat attendu :

$ gcc -std=c2x -Wall -Wextra -pedantic -g p4e5.c -o p4e5 && ./p4e5
Enfant a reçu : Bonjour depuis le parent !

p4e6 - Ping-pong bidirectionnel avec deux pipes

Écrire un programme parent-enfant utilisant deux pipes :

  • Pipe P1 (parent → enfant)

  • Pipe P2 (enfant → parent)

  • Le parent envoie “ping#1”, l’enfant lit et répond “pong#1”

  • Répéter pour N échanges (ex: 5)

  • Afficher chaque message envoyé/reçu

Résultat attendu :

$ gcc -std=c2x -Wall -Wextra -pedantic -g p4e6.c -o p4e6 && ./p4e6
[Parent] Envoi: ping#1
[Enfant] Reçu: ping#1
[Enfant] Envoi: pong#1
[Parent] Reçu: pong#1
[Parent] Envoi: ping#2
...

p4e7 - FIFO (tube nommé) - Writer & Reader

Créer deux programmes séparés qui communiquent via FIFO :

Programme p4e7_writer.c :

  • Crée mkfifo("canal", 0666) si besoin (gérer EEXIST)

  • Ouvre “canal” en écriture (O_WRONLY) — bloquant jusqu’à un lecteur

  • Envoie “Hello FIFO:raw-latex:n” puis ferme

  • Supprime la FIFO avec unlink("canal")

Programme p4e7_reader.c :

  • Ouvre “canal” en lecture (O_RDONLY) — bloquant jusqu’à un écrivain

  • Lit tout jusqu’à EOF et affiche

  • Ferme le descripteur

Test :

$ gcc p4e7_reader.c -o reader && gcc p4e7_writer.c -o writer
$ ./reader &
[1] 12345
$ ./writer
Hello FIFO
[1]+  Done

p4e8 - Mini-shell avec commandes simples et background

Écrire un mini-shell qui :

  • Affiche un prompt mini-shell>

  • Lit une ligne de commande (avec fgets)

  • Parse les arguments (séparateur espace simple)

  • Lance les commandes dans un fork fork + execvp puis waitpid sur l’enfant

  • Commande interne exit pour quitter le shell

Vous pouvez vous aider de ce tutoriel : https://brennan.io/2015/01/16/write-a-shell-in-c/

Résultat attendu :

$ gcc -std=c2x -Wall -Wextra -pedantic -g p4e8.c -o p4e8 && ./p4e8
mini-shell> echo hello
hello
mini-shell> sleep 5 &
[bg] PID=12350 lancé en arrière-plan
mini-shell> date
mer. 15 oct. 2025 14:30:12 CEST
mini-shell> exit
Au revoir !

Vous pouvez ajouter petit à petit des éléments à votre shell comme pouvoir lancer des commandes en background quand la ligne se termine par &, créer les fonctions comme cd ou history (voir la commande help dans un terminal bash si vous voulez de l’inspiration).