Devoirs Terminale

Liste des fichiers Notebook

DM 7 - Terminale NSI

Sujet du bac Spécialité NSI 2024 - Amérique du Nord

Introduction

Cet exercice porte sur la programmation Python, la programmation orientée objet, les structures de données (file), l’ordonnancement et l’interblocage.

Question 1

Citer les trois états dans lesquels un processus peut se trouver.

Les trois états possibles pour un processus sont :

  1. Prêt
  2. En cours d'exécution
  3. Bloqué (ou en attente)

Question 2

Citer les deux seuls états possibles pour un processus dans ce contexte.

Dans ce contexte simplifié, les deux états possibles sont :

  1. En cours d'exécution
  2. En attente dans la file

Question 3

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

Question 4

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: 
Texte alternatif

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: 
Texte alternatif

Question 5

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

Question 6

É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

Question 7

Montrer que l’ordre d’exécution donné en exemple aboutit à une situation d’interblocage.

Texte alternatif
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.