Exercice 2 Asie – Bac NSI 2025 – Jour 2
On souhaite élaborer un programme système permettant de gérer l'ordre d'exécution des processus sur le processeur.
mots clés: programmation, files processus, POO
🔎 Voir les exercices similaires ↓
Asie – Bac NSI 2025 – Jour 2 Énoncé de l'exercice 2
Cet exercice porte sur la programmation Python, la gestion des processus.
On souhaite élaborer un programme système permettant de gérer l’ordre d’exécution des processus sur le processeur.
Donner le nom de ce type de programme.
Donner les différents états possibles d’un processus.
Chaque processus dispose d’une valeur de priorité. Un processus est prioritaire sur un autre processus si sa valeur de priorité est plus petite. Ainsi pour rendre un processus moins prioritaire, il faut augmenter sa valeur de priorité, par exemple en la faisant passer de 2 à 3.
Fonctionnement du programme gérant l’ordre d’exécution des processus :
On dispose d'une liste dont les éléments sont des files de processus. La première file contient les processus ayant la valeur de priorité la plus élevée 0, la seconde ceux ayant la valeur de priorité 1, etc. À l'arrivée d'un nouveau processus :
Attribuer au nouveau processus la valeur de priorité la plus élevée 0 ;
Placer le nouveau processus dans la file d'attente correspondant à sa valeur de priorité (c’est-à-dire la première file de la liste).
À chaque cycle d'horloge :
S'il n'y a pas de processus en cours d'exécution et s'il reste des processus en attente :
Sélectionner un processus avec la priorité la plus élevée dans l'une des files d'attente non vides ;
Élire ce processus comme nouveau processus en cours d'exécution ;
Sinon si un processus est en cours d'exécution :
Si le processus a terminé son exécution, le retirer du processeur ;
Sinon,
incrémenter le temps d'utilisation du processus ;
Si des processus de priorité supérieure ou égale attendent :
Retirer le processus en cours d'exécution du processeur ;
Réduire sa priorité de 1 et le mettre dans la file d'attente correspondant à sa priorité ;
Élire un processus dont la priorité est la plus élevée parmi les processus des files d'attente non vides ;
Sinon, réduire sa priorité de 1 et continuer à exécuter le processus en cours d'exécution.
Parmi les propositions suivantes, donner la structure la plus adaptée pour stocker les processus d’une même priorité :
Proposition 1 : Liste
Proposition 2 : File
Proposition 3 : Pile
Pour représenter le processus, on utilise une classe Processus qui possède les variables d’instances PID (l’identifiant du processus), priorite (la priorité du processus), temps_utilisation sur le CPU et le temps nécessaire à son exécution temps_CPU.
Compléter le constructeur de la classe Processus :
class Processus:
...(self, ..., priorite, temps_CPU):
... priorite = priorite
... PID = ...
self.temps_utilisation = 0
self.temps_CPU = temps_CPU
On considère les trois processus suivants :
P1 = Processus(PID=1, priorite=0, temps_CPU=10)
P2 = Processus(PID=2, priorite=0, temps_CPU=7)
P3 = Processus(PID=3, priorite=0, temps_CPU=5)
On a donc liste_files=[[P3, P2, P1], [], []].
Compléter la simulation suivante, dans laquelle la variable CPU contient le processus en cours d’exécution :
Cycle 1: CPU=P1 liste_files=[[P3, P2], [], []]
Cycle 2: CPU=P2 liste_files=[[P3], [P1], []]
Cycle 3: CPU=P3 liste_files=[[], [...], []]
Cycle 4: CPU=P3 liste_files=[[], [...], [...]]
Cycle 5: CPU=... liste_files=[[], [...], [...]]
Dans les questions 6 et 7, on dispose :
d’un processus qui nécessite un temps d’utilisation de 1000 pour terminer ;
d’un nombre important de processus dont le temps d’utilisation pour terminer est de 4 où l’on suppose de plus que chaque processus terminé est remplacé par un nouveau processus similaire.
Expliquer pourquoi le processus qui nécessite un long temps d’utilisation du CPU risque de ne jamais terminer avec le programme de gestion de l’ordre des processus ci-dessus (indiquer notamment la priorité du processus long au bout de quelques temps).
Pour régler ce phénomène, on décide d’ajouter la variable d’instance temps_d_attente au processus, et on définit une constante appelée Max_Temps qui correspond au temps maximum qu’un processus attend avant de remonter sa priorité. L’idée est qu’à chaque cycle, le temps_d_attente augmente. Ainsi, si sa valeur dépasse Max_Temps, alors sa priorité augmente.
Expliquer pourquoi le processus qui nécessite un temps long d’utilisation du CPU ne risque plus de ne jamais terminer avec ce nouveau programme de gestion de l’ordre des processus.
Écrire une fonction meilleur_priorite qui renvoie None s’il n’y a plus de processus et la priorité de l’un des processus les plus prioritaires de la liste des files d’attente dans le cas contraire.
def meilleur_priorite(liste_files):
...
Exemple :
# p1, p2 et p3 sont des instances de la classe 'Processus'
>>> liste_files = [[], [p2], [p3, p1]]
>>> meilleur_priorite(liste_files)
Écrire une fonction prioritaire qui renvoie None si aucune des files d’attente de la liste ne contient un processus et qui renvoie l’un des processus parmi les plus prioritaires sinon (dans ce cas la fonction prioritaire supprimera le processus choisi de la file d’attente dans laquelle il se trouvait).
def prioritaire(liste_files):
...
On pourra utiliser liste.pop(i) pour renvoyer l’élément de la liste à la position i, tout en le supprimant de la liste.
Écrire une fonction gerer qui récupère le processus en cours d’exécution p ainsi que la liste des files d’attente liste_files et qui implémente le programme donné en début d’énoncé pour gérer les processus.
def gerer(p, liste_files):
...
Asie – Bac NSI 2025 – Jour 2 Correction de l'exercice 2
1) Nom du programme
Il s’agit d’un ordonnanceur (scheduler).
2) États possibles d’un processus
Les principaux états sont :
Prêt (en attente du processeur)
Élu (en cours d’exécution)
Bloqué (en attente d’un événement, par exemple une ressource)
Terminé
3) Structure la plus adaptée
✔ Réponse : proposition 2, une file.
4) Constructeur de la classe Processus
class Processus:
def __init__(self, PID, priorite, temps_CPU):
self.priorite = priorite
self.PID = PID
self.temps_utilisation = 0
self.temps_CPU = temps_CPU
5) Simulation
On part de :
liste_files = [[P3, P2, P1], [], []]
Au cycle 1, P1 est élu alors que la file vaut [P3, P2, P1] : la tête de chaque file est le dernier élément de la liste. Un processus rétrogradé arrive donc au début de la file suivante.
Cycle 3 : P2 (priorité 0) a utilisé le CPU et P3, de même priorité, attend : P2 est retiré, passe en priorité 1 (file 1 : [P2, P1]) et P3 est élu.
Cycle 4 : P3 a utilisé le CPU ; le meilleur processus en attente a la priorité 1, moins prioritaire que P3 (0) : P3 continue, mais sa priorité passe à 1.
Cycle 5 : P1 et P2 attendent avec la priorité 1, égale à celle de P3 : P3 est retiré, passe en priorité 2 (file 2 : [P3]) et la tête de la file 1, P1, est élue.
Cycle 1: CPU=P1 liste_files=[[P3, P2], [], []]
Cycle 2: CPU=P2 liste_files=[[P3], [P1], []]
Cycle 3: CPU=P3 liste_files=[[], [P2, P1], []]
Cycle 4: CPU=P3 liste_files=[[], [P2, P1], []]
Cycle 5: CPU=P1 liste_files=[[], [P2], [P3]]
6) Pourquoi le long processus peut ne jamais terminer?
Le processus long :
démarre priorité 0
est rétrogradé à 1
puis 2
puis 3
etc.
Le processus 1000 va avoir une priorité qui va donc diminuer de 1 après chaque exécution. Pendant ce temps, de nouveaux petits processus arrivent en priorité 0.
Il se retrouve donc avec une priorité de plus en plus faible (valeur numérique grande). Il n’est plus jamais sélectionné.
C’est un phénomène appelé famine (starvation).
7) Pourquoi le nouveau système règle le problème?
Avec temps_d_attente :
Si un processus attend trop longtemps,
Sa priorité augmente (valeur numérique diminue),
Il redevient prioritaire.
Cela empêche la famine. On parle de mécanisme de vieillissement (aging).
8) Fonction meilleur_priorite
def meilleur_priorite(liste_files):
for i in range(len(liste_files)):
if liste_files[i] != []:
return i
return None
9) Fonction prioritaire
def prioritaire(liste_files):
for i in range(len(liste_files)):
if liste_files[i] != []:
return liste_files[i].pop() # tête de file = dernier élément
return None
10) Fonction gerer
def gerer(p, liste_files):
if p is None: # aucun processus en cours
return prioritaire(liste_files) # (None si les files sont vides)
if p.temps_utilisation >= p.temps_CPU: # processus terminé :
return None # on le retire du processeur
p.temps_utilisation = p.temps_utilisation + 1
meilleure = meilleur_priorite(liste_files)
p.priorite = p.priorite + 1 # sa priorité baisse dans les deux cas
if meilleure is not None and meilleure < p.priorite:
# un processus de priorité supérieure ou égale attend
while len(liste_files) <= p.priorite: # file pas encore créée
liste_files.append([])
liste_files[p.priorite].insert(0, p) # en queue de file
return prioritaire(liste_files)
return p # p continue son exécution
La fonction renvoie le processus en cours d’exécution à la fin du cycle (None s’il n’y en a pas).
Une erreur, un oubli ? Écrivez-moi : frederic.peuriere@lfcl.pt
🔎 Exercices sur des thèmes similaires
-
Polynésie 2025 – jour 2 – exercice 2
programmation, POO, BDD, SQL — Difficulté : 🔥🔥🔥🔥🔥 -
Centres étrangers 2024 – jour 2 – exercice 1
programmation, POO, récursivité — Difficulté : 🔥🔥🔥🔥🔥 -
Centres étrangers 2024 – jour 1 – exercice 3
programmation, POO, BDD, SQL — Difficulté : 🔥🔥🔥🔥🔥 -
Asie 2024 – jour 2 – exercice 2
programmation, POO, structures de données linéaires — Difficulté : 🔥🔥🔥🔥🔥 -
Asie 2024 – jour 1 – exercice 3
programmation, POO, BDD, SQL — Difficulté : 🔥🔥🔥🔥🔥 -
Asie 2024 – jour 1 – exercice 1
programmation, POO, algorithmique — Difficulté : 🔥🔥🔥🔥🔥