Processus et tourniquet

Lors de son fonctionnement, le système d'exploitation d'un ordinateur doit partager la ressource de calcul entre différents processus. Pour ce faire, il met en œuvre un algorithme d'ordonnancement. On s'intéresse dans cet exercice à l'algorithme du tourniquet (round-robin en anglais).

Dans cet algorithme :

  • chaque processus est associé à une certaine durée d'exécution ;
  • initialement, les processus sont tous placés dans une file ;
  • à chaque itération de l'algorithme :
    • le processeur pioche le premier processus de la file et l'exécute durant un certain de temps de calcul appelé quantum ;
    • si, à l'issue de ce temps de calcul, le processus n'est pas terminé, il est ré-enfilé ;
  • l'algorithme s'arrête lorsque la file est vide.

On fournit deux classes Processus et File permettant de mettre en œuvre cet algorithme. Ces classes sont d'ores et déjà importées dans l'éditeur.

La classe Processus

Cette classe permet de représenter un processus. Un objet de type Processus est caractérisé par deux attributs :

  • pid : nombre entier positif permettant d'identifier le processus. On note pid pour « process id » ;
  • _duree : nombre entier positif ou nul représentant la durée d'exécution restante, exprimée en ms.

Les exemples ci-dessous présentent l'interface de la classe.

>>> p = Processus(123, 5)  # création d'un processus
>>> p                      # affichage
(PID=123 ; durée=5)
>>> p.pid                  # accès au PID
123
>>> p.execute(3)           # exécution durant 3 ms
>>> p.est_fini()           # le processus est-il fini ?
False
>>> p.execute(3)           # exécution durant 3 ms -> bloque à 0
>>> p1.est_fini()
True
Code (pour information)
class Processus:
    """Classe définissant un processus"""
    def __init__(self, pid, duree):
        self.pid = pid
        self._duree = duree  # ne pas modifier cet attribut

    def execute(self, quantum):
        """Diminue la durée d'exécution restante de quantum. Bloque à 0"""
        self._duree = max(0, self._duree - quantum)

    def est_fini(self):
        """Renvoie le booléen répondant à la question 'Le processus est-il terminé ?'"""
        return self._duree == 0

    def __repr__(self):
        """Affichage"""
        return f"(PID={self.pid} ; durée={self._duree})"
La classe File

Cette classe permet de représenter une file. Les exemples ci-dessous présentent l'interface de la classe.

>>> f = File()
>>> f.est_vide()
True
>>> f.enfile("a")
>>> f.enfile("b")
>>> f.enfile("c")
>>> f
(queue) c -> b -> a (tête)
>>> f.defile()
a
>>> f
(queue) c -> b (tête)
>>> f.est_vide()
False
Code (pour information)
from collections import deque

class File:
    """Classe définissant une structure de file"""

    def __init__(self):
        self.valeurs = deque([])

    def est_vide(self):
        """Renvoie le booléen True si la file est vide, False sinon"""
        return len(self.valeurs) == 0

    def enfile(self, x):
        """Place x à la queue de la file"""
        self.valeurs.appendleft(x)

    def defile(self):
        """Retire et renvoie l'élément placé à la tête de la file.
        Provoque une erreur si la file est vide
        """
        if self.est_vide():
            raise ValueError("La file est vide")
        return self.valeurs.pop()

    def __repr__(self):
        """Convertit la file en une chaîne de caractères"""
        return f"{list(self.valeurs)}"

Écrire la fonction tourniquet qui prend en paramètres une file de processus file ainsi qu'un entier strictement positif quantum représentant la durée d'exécution allouée par l'algorithme à chaque itération (en ms).

Cette fonction renvoie la liste ordonnée des pid des processus exécutés.

On garantit que les processus présents dans la file ont tous des PID différents.

Exemples
>>> f = File()
>>> f.enfile(Processus(0, 5))
>>> f.enfile(Processus(1, 2))
>>> tourniquet(f, 1)  # chaque processus est exécuté durant 1 ms
[0, 1, 0, 1, 0, 0, 0]
>>> f = File()
>>> f.enfile(Processus(8, 5))
>>> f.enfile(Processus(26, 2))
>>> f.enfile(Processus(7, 6))
>>> tourniquet(f, 6)  # chaque processus est exécuté durant 6 ms
[8, 26, 7]
###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10
.128013beqn,49vi[3mo5_txPhklpwf(: cg.a=ryS6]u/72)s18d050U0c0q0F0j0v0R0B0C0v0F0R0R0G010q0j0w010406050R0M0m0m0F0H0I040J0n0v0M0/0n0e050N0_0{0}0 0@0w04051f181i0N1f0@0U0j0i0%0)0+0-0t0j0D0t0v1w0t0q0=050Y0b0v0c1r0*0,011v1x1z1x0q1F1H1D0q0H1g0q0t0%120R0w0F0e0-0P011J1t010y0!0c0e0F0m0c1D1$1(1-1L1:1H1?1^0=0a0B0s0H0n0w0n0R0j150e0B0W1!0H0H0c0C2d181{0e1g0N1Y2q1V1X1W1E0U1}0-1z0e1=2a1D1o1q0(1K2A0j2C0e0n2G1D0w2j1g2o2q2U0^1%2e2I1.2N0H0|0v0=0S2n2Y0?2X1|2!1L2$2(0=0P2,1(2.2o2z012?0F2)040l2`2p0@2}2;0-30320g352|2Y2~3b0=0o3e373g392 0n2%310=0K3l2/2Z1s2=3q2@040O3v383y3a3A3s040T3E3n3G3p3r320h3e1j2S182G2t0U1X2y3o0C2O1_1g3X1h3V2W192-053%0W2T3N2J010u0=0W0y3T3F3_0x0=0B3 3^2#0y0=0q0n0M0H0e0j0d0M0X452:3O0;040z4j3x3_0e0=1 0c4p2~4m0f3e44402#0=4g1(0q0`4w3o4m0Q0A3l0B4P4B462=0=3q0U2j4A3w2~0n0=0G4Y4C1L4m0k0L4O4Q4Z3o3{040x1v1H4(4S0-0n42042N0q4`4k4r4t1;4J3O4#040E5754040c0R0q0p0i0j0W5c1.4m0z4M4.4Q4/4)3a0=2R0n0C5f0_0R524q1.594%3/2{4R534D044u5m1L595b5I2p4:3O4s043}565T3@5L4*0=5p5r5s5K5E4T044V4X5#5V3_5R5P5v040F0w0w1=0U5`015o625X5x5z0+0M5C5?5u015_6c4{2 5w5k624L5+5s5@5M675A6a626f2W6d5X0c0r2k144v6g5%0-646E5.5{4F0e4H0m6l0=0Q6n5t6h4=0j3~5#5-4!4~505D3h5w27685B6u0=5S6w6h6y5g0p1:4e6P4n5q5#065,6 6Z3o5X5O6I4!6.650=1=746:6F635)78046r696b7c6J7e046R6}6o6d4=2j4H4d6%724U0H4W6D2U0@0N3=0c2q2R7H3W1p3Y2t2w2r0F1G7K0N3X7E0W0Y0!0R04.