Sujet du bac Spécialité NSI 2024 - Amérique du Nord
Cet exercice porte sur la programmation Python, la programmation orientée objet, les structures de données (file), l’ordonnancement et l’interblocage.
Citer les trois états dans lesquels un processus peut se trouver.
Les trois états possibles pour un processus sont :
Citer les deux seuls états possibles pour un processus dans ce contexte.
Dans ce contexte simplifié, les deux états possibles sont :
Rectifier la classe File
pour que la méthode defile
renvoie None
lorsque la file est vide.
class File:
def __init__(self):
self.contenu = []
def enfile(self, element):
self.contenu.append(element)
def defile(self):
if self.est_vide():
return None
return self.contenu.pop(0)
def est_vide(self):
return len(self.contenu) == 0
Compléter le chronogramme pour les processus p1
, p2
, p3
, et p4
.
# Code en entier pour comprendre, mais pas demandé !!!
# Classe File modifiée pour pouvoir afficher son contenu
class File:
def __init__(self):
self.contenu = []
def enfile(self, element):
self.contenu.append(element)
def defile(self):
if self.est_vide():
return None
return self.contenu.pop(0)
def est_vide(self):
return len(self.contenu) == 0
def __str__(self):
# Représentation lisible de la file pour affichage (ordre inversé)
return ' -> '.join(proc.nom for proc in reversed(self.contenu))
# Classe Processus
class Processus:
def __init__(self, nom, duree):
self.nom = nom
self.duree = duree
def execute_un_cycle(self):
if self.duree > 0:
self.duree -= 1
def est_fini(self):
return self.duree == 0
# Classe Ordonnanceur
class Ordonnanceur:
def __init__(self):
self.temps = 0
self.file = File()
def ajoute_nouveau_processus(self, proc):
'''Ajoute un nouveau processus dans la file de l'ordonnanceur.'''
self.file.enfile(proc)
def tourniquet(self):
'''Effectue une étape d'ordonnancement et renvoie le nom du processus élu.'''
self.temps += 1
if not self.file.est_vide():
proc = self.file.defile()
proc.execute_un_cycle()
if not proc.est_fini():
self.file.enfile(proc)
return proc
return None
# Définition des processus avec leur nom et leur durée en cycles
A = Processus("A", 3)
B = Processus("B", 4)
C = Processus("C", 3)
D = Processus("D", 5)
# Dictionnaire associant chaque cycle à un processus créé à ce moment
depart_proc = {
0: D,
1: B,
2: A,
4: C
}
# Création de l'ordonnanceur
ordonnanceur = Ordonnanceur()
# Simulation
while True:
if ordonnanceur.temps in depart_proc:
ordonnanceur.ajoute_nouveau_processus(depart_proc[ordonnanceur.temps])
# Afficher l'état initial de la file avant le cycle
print(f'File initial: {ordonnanceur.file}', end="")
process_elected = ordonnanceur.tourniquet()
if process_elected is None:
break
# Afficher le processus élu et l'état final de la file
print(f' Cycle {ordonnanceur.temps}: ({process_elected.nom},{process_elected.duree}) File final: {ordonnanceur.file}')
File initial: D Cycle 1: (D,4) File final: D File initial: B -> D Cycle 2: (D,3) File final: D -> B File initial: A -> D -> B Cycle 3: (B,3) File final: B -> A -> D File initial: B -> A -> D Cycle 4: (D,2) File final: D -> B -> A File initial: C -> D -> B -> A Cycle 5: (A,2) File final: A -> C -> D -> B File initial: A -> C -> D -> B Cycle 6: (B,2) File final: B -> A -> C -> D File initial: B -> A -> C -> D Cycle 7: (D,1) File final: D -> B -> A -> C File initial: D -> B -> A -> C Cycle 8: (C,2) File final: C -> D -> B -> A File initial: C -> D -> B -> A Cycle 9: (A,1) File final: A -> C -> D -> B File initial: A -> C -> D -> B Cycle 10: (B,1) File final: B -> A -> C -> D File initial: B -> A -> C -> D Cycle 11: (D,0) File final: B -> A -> C File initial: B -> A -> C Cycle 12: (C,1) File final: C -> B -> A File initial: C -> B -> A Cycle 13: (A,0) File final: C -> B File initial: C -> B Cycle 14: (B,0) File final: C File initial: C Cycle 15: (C,0) File final: File initial:
Le chronogramme complété est :
File initial: p1 Cycle 1: (p1,3) File final: p1
File initial: p3 -> p1 Cycle 2: (p1,2) File final: p1 -> p3
File initial: p2 -> p1 -> p3 Cycle 3: (p3,4) File final: p3 -> p2 -> p1
File initial: p4 -> p3 -> p2 -> p1 Cycle 4: (p1,1) File final: p1 -> p4 -> p3 -> p2
File initial: p1 -> p4 -> p3 -> p2 Cycle 5: (p2,2) File final: p2 -> p1 -> p4 -> p3
File initial: p2 -> p1 -> p4 -> p3 Cycle 6: (p3,3) File final: p3 -> p2 -> p1 -> p4
File initial: p3 -> p2 -> p1 -> p4 Cycle 7: (p4,2) File final: p4 -> p3 -> p2 -> p1
File initial: p4 -> p3 -> p2 -> p1 Cycle 8: (p1,0) File final: p4 -> p3 -> p2
File initial: p4 -> p3 -> p2 Cycle 9: (p2,1) File final: p2 -> p4 -> p3
File initial: p2 -> p4 -> p3 Cycle 10: (p3,2) File final: p3 -> p2 -> p4
File initial: p3 -> p2 -> p4 Cycle 11: (p4,1) File final: p4 -> p3 -> p2
File initial: p4 -> p3 -> p2 Cycle 12: (p2,0) File final: p4 -> p3
File initial: p4 -> p3 Cycle 13: (p3,1) File final: p3 -> p4
File initial: p3 -> p4 Cycle 14: (p4,0) File final: p3
File initial: p3 Cycle 15: (p3,0) File final:
File initial:
Compléter le code de la classe Ordonnanceur
.
class Ordonnanceur:
def __init__(self):
self.temps = 0
self.file = File()
def ajoute_nouveau_processus(self, proc):
'''Ajoute un nouveau processus dans la file de
l'ordonnanceur. '''
self.file.enfile(proc)
def tourniquet(self):
'''Effectue une étape d'ordonnancement et renvoie le nom
du processus élu.'''
self.temps += 1
if not self.file.est_vide():
proc = self.file.defile()
proc.execute_un_cycle()
if not proc.est_fini():
self.file.enfile(proc)
return proc.nom
return None
Écrire un programme utilisant les processus p1
, p2
, p3
, p4
et depart_proc
.
# Définir les processus et leur moment de création
p1 = Processus('p1', 4)
p2 = Processus('p2', 3)
p3 = Processus('p3', 5)
p4 = Processus('p4', 3)
depart_proc = {0: p1, 1: p3, 2: p2, 3: p4}
# Création de l'ordonnanceur
ordonnanceur = Ordonnanceur()
# Simulation
while True:
if ordonnanceur.temps in depart_proc:
ordonnanceur.ajoute_nouveau_processus(depart_proc[ordonnanceur.temps])
process_elected = ordonnanceur.tourniquet()
if process_elected is None:
break
# Afficher le processus élu et l'état final de la file
print(f' Cycle {ordonnanceur.temps}: {process_elected}')
Cycle 1: p1 Cycle 2: p1 Cycle 3: p3 Cycle 4: p1 Cycle 5: p2 Cycle 6: p3 Cycle 7: p4 Cycle 8: p1 Cycle 9: p2 Cycle 10: p3 Cycle 11: p4 Cycle 12: p2 Cycle 13: p3 Cycle 14: p4 Cycle 15: p3
Montrer que l’ordre d’exécution donné en exemple aboutit à une situation d’interblocage.
Dans l’exécution :
Cycle 1 : D acquiert le fichier,
Cycle 2 : D fais des Calculs,
Cycle 3 : B acquiert le clavier,
Cycle 4 : D acquérir le clavier,
Cycle 5 : A acquiert le GPU,
Cycle 6 : B veut acquiert le fichier, mais il est pris par D. On a donc une situation d’interblocage.