Exercices - Architectures, systèmes d'exploitation et réseaux¶
Systèmes sur puce¶
Exercice 1 - Composants d'un SoC¶
a. Citer au moins six composants que l'on trouve typiquement dans le SoC d'un smartphone.
b. Donner deux avantages de l'intégration de tous ces composants sur une seule puce.
c. Expliquer pourquoi un SoC consomme moins d'énergie que des composants séparés sur une carte mère.
Solution
a. CPU (processeur), GPU (processeur graphique), mémoire cache, modem 4G/5G, Wi-Fi, Bluetooth, GPS, NPU (processeur IA), ISP (processeur d'image), PMU (gestion d'énergie), contrôleur vidéo, DSP.
b. Vitesse de communication accrue (distances très courtes entre composants) et consommation d'énergie réduite (moins de pertes, gestion fine de l'énergie).
c. Les signaux parcourent des distances de quelques millimètres (contre plusieurs centimètres sur une carte mère), ce qui réduit les pertes électriques. De plus, le PMU peut mettre en veille sélectivement les composants inutilisés.
Processus et ordonnancement¶
Exercice 2 - Vocabulaire des processus¶
a. Quelle est la différence entre un programme et un processus ?
b. Un utilisateur ouvre deux fenêtres du navigateur Web. Combien de programmes et combien de processus cela représente-t-il ?
c. Citer les quatre états principaux d'un processus.
Solution
a. Un programme est un fichier stocké sur le disque. Un processus est une instance de ce programme en cours d'exécution, avec son propre espace mémoire et son PID.
b. Un seul programme (le navigateur), mais au moins deux processus (un par fenêtre, voire plus avec les processus de rendu).
c. Prêt, élu (en exécution), bloqué (en attente), terminé.
Exercice 3 - Ordonnancement tourniquet¶
Trois processus P1, P2, P3 arrivent dans cet ordre avec les durées d'exécution suivantes :
- P1 : 6 unités de temps
- P2 : 3 unités de temps
- P3 : 4 unités de temps
L'ordonnanceur utilise le tourniquet (Round Robin) avec un quantum de 2 unités de temps.
a. Dérouler l'exécution en indiquant quel processus s'exécute à chaque intervalle.
b. À quel instant chaque processus se termine-t-il ?
c. Calculer le temps de séjour moyen (temps entre l'arrivée et la terminaison).
Solution
a. Déroulement :
| Intervalle | Processus | P1 restant | P2 restant | P3 restant |
|---|---|---|---|---|
| 0-2 | P1 | 6 → 4 | 3 | 4 |
| 2-4 | P2 | 4 | 3 → 1 | 4 |
| 4-6 | P3 | 4 | 1 | 4 → 2 |
| 6-8 | P1 | 4 → 2 | 1 | 2 |
| 8-9 | P2 | 2 | 1 → 0 ✓ | 2 |
| 9-11 | P3 | 2 | - | 2 → 0 ✓ |
| 11-13 | P1 | 2 → 0 ✓ | - | - |
b. P2 se termine à t = 9, P3 à t = 11, P1 à t = 13.
c. Temps de séjour : P1 = 13, P2 = 9, P3 = 11. Moyenne = (13 + 9 + 11) / 3 = 11 unités.
Exercice 4 - Interblocage¶
a. Décrire une situation de la vie courante qui illustre un interblocage (autre que le carrefour).
b. Deux processus P1 et P2 ont besoin des ressources R1 (imprimante) et R2 (fichier) :
- P1 demande R1, puis R2 ;
- P2 demande R2, puis R1.
Expliquer comment un interblocage peut se produire. Illustrer avec un diagramme temporel.
c. Proposer une solution pour éviter cet interblocage.
Solution
a. Deux personnes face à face dans un couloir étroit : chacune attend que l'autre recule pour passer, mais aucune ne bouge.
b. Diagramme temporel :
| Instant | P1 | P2 |
|---|---|---|
| t1 | Obtient R1 | Obtient R2 |
| t2 | Demande R2 → bloqué (R2 détenue par P2) | Demande R1 → bloqué (R1 détenue par P1) |
P1 attend R2 (détenue par P2) et P2 attend R1 (détenue par P1) : interblocage.
c. Imposer un ordre d'acquisition : tous les processus doivent demander R1 avant R2. Ainsi, P2 demanderait d'abord R1 (occupée par P1), attendrait, puis P1 obtiendrait R2, terminerait, libérerait R1, et P2 pourrait continuer.
Protocoles de routage¶
Exercice 5 - Tables de routage RIP¶
Soit le réseau suivant :
Tous les liens ont un coût identique (1 saut). Le routeur A connaît initialement ses voisins B et E.
a. Donner la table de routage initiale de A.
b. B envoie son vecteur : B connaît A (1), C (1). Mettre à jour la table de A.
c. E envoie son vecteur : E connaît A (1), F (1). Mettre à jour la table de A.
d. Après convergence complète, donner la table de routage finale de A.
Solution
a. Table initiale :
| Destination | Prochain | Sauts |
|---|---|---|
| B | B | 1 |
| E | E | 1 |
b. Après vecteur de B : ajout de C via B (2 sauts).
| Destination | Prochain | Sauts |
|---|---|---|
| B | B | 1 |
| C | B | 2 |
| E | E | 1 |
c. Après vecteur de E : ajout de F via E (2 sauts).
| Destination | Prochain | Sauts |
|---|---|---|
| B | B | 1 |
| C | B | 2 |
| E | E | 1 |
| F | E | 2 |
d. Table finale (après convergence) :
| Destination | Prochain | Sauts |
|---|---|---|
| B | B | 1 |
| C | B | 2 |
| D | B | 3 |
| E | E | 1 |
| F | E | 2 |
| G | E | 3 |
| H | B | 4 (ou E, 4) |
Exercice 6 - Coûts OSPF¶
Soit le réseau suivant avec les coûts indiqués :
a. Calculer le coût du chemin A → B → C.
b. Calculer le coût du chemin A → D → E → F → C.
c. Quel chemin OSPF choisirait-il pour aller de A à C ? Et RIP ?
d. Si le débit de référence est 10⁸ bit/s et que le lien B-C a un débit de 10 Mbit/s, vérifier le coût indiqué.
Solution
a. A → B → C : coût = 1 + 10 = 11.
b. A → D → E → F → C : coût = 5 + 1 + 1 + 1 = 8.
c. OSPF choisit le chemin de coût minimal : A → D → E → F → C (coût 8). RIP choisit le chemin avec le moins de sauts : A → B → C (2 sauts vs 4 sauts).
d. Coût = 10⁸ / 10⁷ = 10. Le coût indiqué (10) est correct.
Sécurisation des communications¶
Exercice 7 - Chiffrement de César en Python¶
a. Chiffrer le message « informatique » avec un décalage de 5.
b. Déchiffrer le message « qjfwjyj » avec un décalage de 5.
c. Un message chiffré par César contient « g » comme lettre la plus fréquente. En sachant que la lettre la plus fréquente en français est « e », déduire la clé utilisée et déchiffrer « gnhtkngxg ».
Solution
a. i→n, n→s, f→k, o→t, r→w, m→r, a→f, t→y, i→n, q→v, u→z, e→j → « nsktwrfynvzj ».
b. q→l, j→e, f→a, w→r, j→e, y→t, j→e → « learete » soit « l'aérété » → « learete ».
c. Si « g » correspond à « e », le décalage est g - e = 7 - 5 = 2. En déchiffrant avec un décalage de 2 : g→e, n→l, h→f, t→r, k→i, n→l, g→e, x→v, g→e → « elfrileve » → « el frilève » → en vérifiant : « elfrileve ».
En pratique, la clé est bien 2 et on applique un décalage de -2 à chaque lettre.
Exercice 8 - Symétrique vs asymétrique¶
a. Compléter le tableau :
| Critère | Chiffrement symétrique | Chiffrement asymétrique |
|---|---|---|
| Nombre de clés | ? | ? |
| Vitesse | ? | ? |
| Problème principal | ? | ? |
| Exemple d'algorithme | ? | ? |
b. Pourquoi utilise-t-on un chiffrement hybride pour HTTPS au lieu d'un chiffrement purement asymétrique ?
c. Ordonner les étapes d'une connexion HTTPS :
- Le navigateur chiffre une clé symétrique avec la clé publique du serveur.
- Le serveur envoie son certificat et sa clé publique.
- Les données sont échangées avec le chiffrement symétrique.
- Le navigateur demande une connexion HTTPS.
- Le serveur déchiffre la clé symétrique avec sa clé privée.
Solution
a.
| Critère | Chiffrement symétrique | Chiffrement asymétrique |
|---|---|---|
| Nombre de clés | 1 (partagée) | 2 (publique + privée) |
| Vitesse | Rapide | Lent |
| Problème principal | Échange de la clé secrète | Lenteur, clés longues |
| Exemple d'algorithme | AES | RSA |
b. Le chiffrement asymétrique est trop lent pour chiffrer de grandes quantités de données. On l'utilise uniquement pour échanger la clé symétrique de manière sécurisée, puis on utilise le chiffrement symétrique (rapide) pour les données.
c. Ordre : 4 → 2 → 1 → 5 → 3.
Activités¶
🧪 Activité 1 - Observer les processus¶
Sur votre ordinateur :
- Ouvrir le gestionnaire de processus (Gestionnaire des tâches sous Windows,
topouhtopsous Linux) ; - Identifier le processus qui consomme le plus de CPU ;
- Identifier le processus qui consomme le plus de mémoire ;
- Lancer un script Python en boucle infinie et repérer son PID ;
- Terminer ce processus depuis le gestionnaire.
🧪 Activité 2 - Interblocage débranché¶
Par groupes de 4, simuler un interblocage :
- Chaque élève représente un processus ;
- On dispose de 2 crayons (ressources R1 et R2) ;
- Chaque élève a besoin des 2 crayons pour écrire un mot ;
- Deux élèves prennent chacun un crayon → interblocage ;
- Trouver ensemble une stratégie pour éviter cette situation.
🧪 Activité 3 - Simuler le routage RIP en Python¶
Écrire un programme Python qui simule le protocole RIP sur un réseau modélisé par un dictionnaire d'adjacence. Le programme doit :
- Initialiser les tables de routage (chaque routeur connaît ses voisins) ;
- Simuler les échanges de vecteurs de distance ;
- Afficher l'évolution des tables de routage jusqu'à convergence.
Solution
def initialiser_tables(reseau):
tables = {}
for routeur, voisins in reseau.items():
tables[routeur] = {}
for voisin in voisins:
tables[routeur][voisin] = (voisin, 1)
return tables
def mise_a_jour(tables, reseau):
modifie = False
for routeur in reseau:
for voisin in reseau[routeur]:
for dest, (prochain, sauts) in tables[voisin].items():
if dest == routeur:
continue
nouveau_cout = sauts + 1
if dest not in tables[routeur] or nouveau_cout < tables[routeur][dest][1]:
tables[routeur][dest] = (voisin, nouveau_cout)
modifie = True
return modifie
def afficher_table(routeur, table):
print(f"\nTable de routage de {routeur} :")
print(f" {'Destination':<15} {'Prochain':<10} {'Sauts'}")
for dest in sorted(table):
prochain, sauts = table[dest]
print(f" {dest:<15} {prochain:<10} {sauts}")
reseau = {
'A': ['B', 'D'],
'B': ['A', 'C'],
'C': ['B', 'F'],
'D': ['A', 'E'],
'E': ['D', 'F'],
'F': ['C', 'E']
}
tables = initialiser_tables(reseau)
tour = 0
while True:
tour += 1
print(f"\n{'='*40}")
print(f"Tour {tour}")
if not mise_a_jour(tables, reseau):
print("Convergence atteinte !")
break
for routeur in sorted(tables):
afficher_table(routeur, tables[routeur])
Projet¶
🎯 Projet - Simulateur de réseau¶
Créer un programme Python qui simule un mini-réseau :
- L'utilisateur définit les routeurs et les liens (avec coûts) ;
- Le programme calcule les tables de routage selon RIP (nombre de sauts) et OSPF (coûts) ;
- L'utilisateur peut demander la route empruntée par un paquet entre deux routeurs ;
- Le programme affiche la route, le nombre de sauts et le coût total ;
- L'utilisateur peut simuler une panne de lien et observer la mise à jour des tables.
Solution
import heapq
class Reseau:
def __init__(self):
self.graphe = {}
def ajouter_routeur(self, nom):
if nom not in self.graphe:
self.graphe[nom] = {}
def ajouter_lien(self, r1, r2, cout):
self.ajouter_routeur(r1)
self.ajouter_routeur(r2)
self.graphe[r1][r2] = cout
self.graphe[r2][r1] = cout
def supprimer_lien(self, r1, r2):
if r2 in self.graphe.get(r1, {}):
del self.graphe[r1][r2]
del self.graphe[r2][r1]
def route_rip(self, source, destination):
visite = {source: (None, 0)}
file = [source]
while file:
courant = file.pop(0)
for voisin in self.graphe[courant]:
if voisin not in visite:
visite[voisin] = (courant, visite[courant][1] + 1)
file.append(voisin)
chemin = []
noeud = destination
while noeud is not None:
chemin.append(noeud)
noeud = visite[noeud][0]
chemin.reverse()
return chemin, visite[destination][1]
def route_ospf(self, source, destination):
distances = {r: float('inf') for r in self.graphe}
distances[source] = 0
precedent = {r: None for r in self.graphe}
file = [(0, source)]
while file:
dist, courant = heapq.heappop(file)
if dist > distances[courant]:
continue
for voisin, cout in self.graphe[courant].items():
nouvelle_dist = dist + cout
if nouvelle_dist < distances[voisin]:
distances[voisin] = nouvelle_dist
precedent[voisin] = courant
heapq.heappush(file, (nouvelle_dist, voisin))
chemin = []
noeud = destination
while noeud is not None:
chemin.append(noeud)
noeud = precedent[noeud]
chemin.reverse()
return chemin, distances[destination]
reseau = Reseau()
reseau.ajouter_lien('A', 'B', 1)
reseau.ajouter_lien('B', 'C', 10)
reseau.ajouter_lien('A', 'D', 5)
reseau.ajouter_lien('D', 'E', 1)
reseau.ajouter_lien('E', 'F', 1)
reseau.ajouter_lien('F', 'C', 1)
chemin_rip, sauts = reseau.route_rip('A', 'C')
print(f"RIP : {' → '.join(chemin_rip)} ({sauts} sauts)")
chemin_ospf, cout = reseau.route_ospf('A', 'C')
print(f"OSPF : {' → '.join(chemin_ospf)} (coût {cout})")
print("\nSimulation panne du lien B-C...")
reseau.supprimer_lien('B', 'C')
chemin_rip2, sauts2 = reseau.route_rip('A', 'C')
print(f"RIP : {' → '.join(chemin_rip2)} ({sauts2} sauts)")
chemin_ospf2, cout2 = reseau.route_ospf('A', 'C')
print(f"OSPF : {' → '.join(chemin_ospf2)} (coût {cout2})")