Aller au contenu

Temps d'exécution de processus⚓︎

On considère une liste de processus pour lesquels sont précisés les temps d'arrivée, la durée supposée d'exécution.

Etats d'un processus

Un processus peut être dans un des trois états suivants : prêt, élu ou bloqué.

stateDiagram
    [*] --> prêt
    prêt --> élu
    élu --> prêt
    élu --> bloqué
    bloqué --> prêt
    élu --> [*]
Lorsqu'il est créé, un processus obtient l'état prêt. Cependant, dans le cadre de cet exercice, on souhaite simuler qu'un processus puisse avoir une date d'arrivée (correspondant un temps d'horloge). Ainsi, un processus est créé avec l'état non créé (état initial du diagramme représenté par un point noir), et passera à prêt quand il aura atteint sa date d'arrivée.

A l'inverse, le processus passera à l'état terminé (état final du diagramme représenté par un point cerclé de noir) quand sa durée d'exécution sera atteinte.

L'ordonnancement utilisé est le modèle tourniquet. (Les explications de cet ordonnacement peut se retrouver dans l'exercice Processus et tourniquet)

À tour de rôle, l'ordonnanceur attribuera à un processus, une durée QUANTUM pour poursuivre l'exécution. Plusieurs situations peuvent alors se produire :

  • le processus se termine pendant cette période. Il passe à l'état terminé.
  • le processus n'est pas encore terminé à la fin de la période. Il passe à l'état prêt et est de nouveau placé dans la file d'attente.

La fonction temps_execution prend en paramètre une liste de processus ordonnée suivant la valeur de l'attribut arrivee. Elle renvoie un dictionnaire, dont les clés sont les processus et les valeurs la liste des tuples (debut, fin) des exécutions successives du processus.

On définit les classes Processus et File.

La classe Processus

Un processus est un objet de la classe Processus. Il possède les attributs suivants :

  • nom : nom du processus
  • arrivee : heure d'arrivée du processus dans la file d'attente.
  • etat : "élu", "prêt" et "terminé"
  • duree : durée restante supposée d'exécution du processus.

Cette classe est celle travaillée dans l'exercice Etats des processus

Exemple d'utilisation d'un processus :

Exemples
>>> processus_courant = Processus("P1", 3, arrivee = 0)
>>> processus_courant.est_pret(0)
>>> processus_courant
{'etat': 'prêt', 'nom': 'P1', 'arrivee': 0, 'duree': 3}
>>> processus_courant.elit(2)
>>> processus_courant
{'etat': 'élu', 'nom': 'P1', 'arrivee': 0, 'duree': 3}
>>> processus_courant.execute()
>>> processus_courant
{'etat': 'élu', 'nom': 'P1', 'arrivee': 0, 'duree': 2}
>>> processus_courant.execute()
>>> processus_courant
{'etat': 'prêt', 'nom': 'P1', 'arrivee': 0, 'duree': 1}
>>> processus_courant.elit(2)
>>> processus_courant
{'etat': 'élu', 'nom': 'P1', 'arrivee': 0, 'duree': 1}
>>> processus_courant.execute()
>>> processus_courant
{'etat': 'terminé', 'nom': 'P1', 'arrivee': 0, 'duree': 0}
La classe File

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

A noter la méthode tete qui l'élément en tête mais sans le défiler.

>>> f = File()
>>> f.est_vide()
True
>>> f.enfile("a")
>>> f.enfile("b")
>>> f.enfile("c")
>>> f
['a', 'b', 'c']
>>> f.tete()
a
>>> f
['a', 'b', 'c']
>>> f.defile()
a
>>> f
(queue) c -> b (tête)
>>> f.est_vide()
False
Code (pour information)
class File():
    def __init__(self):
        self.file = []

    def est_vide(self):
        return len(self.file) == 0

    def enfile(self, elt):
        self.file.append(elt)

    def defile(self):
        assert not self.est_vide(), "une file vide ne peut être défilée"
        return self.file.pop(0)

    def tete(self):
        return self.file[0]

    def __repr__(self):
        return str(self.file)

On définira deux files :

  • une file arrivees qui contiendra les processus qui vont arriver dans la file de l'ordonnanceur.
  • une file file_attente qui correspond à la file d'attente des processus, gérée par l'ordonnanceur.

Example

On considère 4 processus P1, P2, P3 et P4. Les durées supposées d'exécution et l'heure d'arrivée dans la file d'attente sont résumées dans le tableau suivant :

Processus P1 P2 P3 P4
Durée en unité de temps 3 4 2 1
Heure d'arrivée 1 2 3 4

À chaque passage à l'état élu, l'ordonnanceur donne, ici, 2qt pour continuer l'exécution.

On suppose de plus qu'aucun processus n'est bloqué pendant son exécution.

S'il y a simultanément arrivée d'un processus et passage d'un autre processus de l'état élu à l'état prêt, c'est le processus arrivant qui entre en premier dans la file d'attente.

On peut représenter l'évolution de l'exécution avec le schéma suivant :

gantt
    title Déroulement de l'exécution
    dateFormat  SSS
    axisFormat %L

    section  Arrivée
    p1 : milestone, , 001,
    p1bis : milestone, , 003,
    p2 : milestone, , 002,
    p2bis : milestone, , 005,
    p3 : milestone, , 003,
    p4 : milestone, , 004,

    section Exécution
    P1 : p1,001, 2ms
    P1 : p1bis, after p3, 1ms
    P2 :p2,after p1, 2ms
    P2 :p2bis,after p4, 2ms
    P3: p3, after p2, 2ms
    P4 :p4,after p1bis  , 1ms

Pour une liste de processus, initialement stockés dans une file arrivees dans leur ordre d'arrivée, on souhaite récupérer les informations qui permettent de construire la représentation de la partie basse, à savoir pour chaque processus une liste de couples (debut, fin) donnant les périodes d'exécution du processus. Le tout étant regroupé dans un dictionnaire.

Exemples
>>> QUANTUM = 2
>>> arrivees = File()
>>> arrivees.enfile(Processus("P1", arrivee = 0, duree = 1))
>>> temps_execution(arrivees)
{"P1":[(0, 1)]}
>>> arrivees = File()
>>> arrivees.enfile(Processus("P1", arrivee = 0, duree = 3))
>>> temps_execution(arrivees)
{"P1":[(0, 2), (2,3)]}
>>> arrivees = File()
>>> arrivees.enfile(Processus("P1", arrivee = 1, duree = 3))
>>> temps_execution(arrivees)
{"P1":[(1, 3), (3,4)]}
>>> arrivees = File()
>>> arrivees.enfile(Processus("P1", arrivee = 0, duree = 3))
>>> arrivees.enfile(Processus("P2", arrivee = 1, duree = 3))
>>> temps_execution(arrivees)
{"P1":[(0, 2), (4,5)], "P2":[(2, 4), (5,6)]}

Voici l'algorithme utilisé :

  • L'horloge est initialisée à zéro
  • Tant qu'il reste un processus dans une des deux file ou comme processus courant :
    • Si un nouveau processus arrive, le créer(passer son état de None à prêt), et le mettre dans la file d'attente.
    • Si le processus courant est passé à l'état "prêt"(il a utilisé son quota sans être terminé), le mettre dans la file d'attente. Il n'y a alors plus de processus courant(passage à l'état None).
    • S'il n'y a pas de processus courant et que la file d'attente n'est pas vide :
      • on récupère le processus courant de la file d'attente
      • l'ordonnanceur élit ce processus,
      • on initialise, au temps d'horloge, l'horaire de début du quantum alloué.
    • on incrémente l'horloge
    • Si le processus courant est à l'état "élu"
      • on l'exécute d'un temps d'horloge
      • Si le processus courant n'est pas à l'état "élu"
        • on enregistre sa période d'exécution
        • si le processus courant est passé à l'état "terminé"
          • il n'y a alors plus de processus courant(passage à l'état None).

Compléter le code suivant.

###(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
.128013s3_8ufvy n7aêS1me(P24:twi][h)6obcdUgMx/T0lqAp!Q.rF,}=+Nk95{é050I0r0x0m0z0Q0b0j0H0Q0m0b0b0#010x0z0T010406050b0f0q0q0m0X0i040o0F0Q0f100F0k050N17191b1d150T041m1t051w0N1w1y1t150I0z0h0^0`0|0~0C0z0K0C0Q1M0C0x13050:0G0Q0r1H0{0}011L1N1P1N0x1V1X1T0x0G0F0I1d1U0X1u0x0C0^1g0b0T0m0k0~0u011Z1J010g0=0r0k0m0q0r1T1~20251#281X2b2d130a0j0t0X0F0T0F0b0z1j0k0j0.1|0X0X0r0H2y1m2g0k1u0N1`2L0x1^1@1_0I2i0~1P0k2a2v1T1E1G0_1!2V0z2X0k1;1F1T0T2E1u2J2L2?161 2z2%262,0X1a0Q130j0p2I2`142_2h2|1#2~30320u3520372J2U013c0m31040j0c3g2K153j3a0~3m3o0j0v3s3i2`3k3y320*3C3u3E3w3l0F2 3n320E3J382{1I3b3O3d3p0l3T3v3W3x3Y3Q3p0e3$3L3(3N3P3z0)3.393:3G040p0P3^3V2(3;3Z0p341n363K3_413{0p3f463h48402}3*3o0p3r4e3t3U3F4j130p3B4n3D494i3=4s3I4v4g4q4z3|3S4C4p3M4b3#4I3%4a4r3|3-4N3/4P4F0p3@4T4x3X4F0u3~4Z4h4#3Z0u452?4D4K4Q0u4d4/4J3`4=4m4^4O4y4,4u4}4U4 3+0u4B524!3)4$4H584*5a4,4M5d4E4,4S5i4;4$4Y5m4`4F0c4(5q4V3Z0c4.474_5w3+0c4@5A4~4+5D4|5G535I3o0c51361v2;1m2#2O0I2S3k0H1;2e1u5V1x5T2^4v055!0.2=5M3x130V0J0S0%0O0J0L3C0j5B260F130#5~601#0q0z135F4f660~0(130.0g3C6d010y326j5H3x0g130x0r0q0T0b0d0r0M2F1i0z1k6o5;0112040s6F593l131b0X1F0r0r0b6L5e6H130Z656p6N040R0f200x186V3k6I0D0w3J0j6?5 6#0k6s6w6y6A0H6C6E4v6^6G620464726k6I0+0!6=6@6k6`046t6v6x0C3O0Q0F0K0r6!74637r6M68135u476@736M7g2k0r0d0m1+2a6t7u6W75772?7B6W7g0Y296-3M6I0s0D7d6?7f6s0r2 2*6S7L3k7N7,3M0(0H130Y3n0b7q4C7A7$042:0F0H6T176x5!0f0X6*7/3:7.786#7;130%1k7`4/7|8d130y1L1X89410F6m042,0x8q267X7V3`6O2D6R6T8A8r130W8G2}136T0x0d0h0z0.8K1#7X7Z8c748t200I8x3b137E7G7I0k7K5,6#758J8.6G7g8N8P8R8i5R6#8V8$0~8s6O0k8#8X7C137 810|0f840F8688957M637O367Q3k8e048g2X8T0~6/6;4C067A8k6G6f040z6i729l3M918u0F8w9g3F8C6Q0h6S6U8=6M8:9r6$8^8Q8S9S6W8~9L9G8Z938 6$6P8E9R2^8/8I9V7g6t8-9:6G9$9`9T9=9!9M048^2:0/9V8za04K7%7j0d7l0X7n7pa6136:7!9x9y96048)7H6t8,8{3h6k9Ua88Ba20k7Eah6J9?9N9.9Vaw9}7R6g0raBax418V8W4/9wal9F3:9A9C9+7g98829b0d85878,9+750U9j3haV419n9pat2Ka;619)947P7}a#9a9c9ea+aO619 aJa10/7Ha,9i9+0b23046H0X0n1SaC9u8jaUbp7}ap8+9_8|7s048;b8a9azaNbz3:a7bD4a972s9983a(9da*9KbG8yaiakbpamaK7~bJa$b2bObc769+a?8h3JaTal6kaX9Da~6_bI80bZbMb3bP9kavbd9%aW7=9ob*b 8ra|a,8t8vaZ8(298*arbuau9;bxaEa20b8O9Ya^5:6M8Vbn7zbU7#b=bXb@b1b_b#c4b6b%cC8%aoccaq7Jcob}cib5cG6h7UcO9s137YbTaUa bYcza)9fbQ1#aIbvan0r1Pb{cg9{cUcj6(6*6,cS6X04aRctcu7}0.0G1i0dc?8,0f1lcF907td86$7i6|adafco0j06b,9x7}dd7k7m7odhcMa/a_dm6udedpagdb750$9+7w3|cWcv9z13aYdba!cZbLc#b4b;bwa.b(c1a@bmdGdlcwb0dObNc$c*9hcNc%5=a26~1icL8}cUc|4fcudH6Mb/cacxbKa%dPc.2KcMbyd)b90:e23pcMdTdbbf13010,1h01dX7{d_bV9mdJb:b|d!dNe0d%dQe69Gb7exay2,0qc7dJd7dRan0x6|6z6B2Hc_6Icsd^emcXcweJ6xeL6 eNd,c`0Bcjd#eub`aHezc/aneCaC0Ae+d+eAbH040m0T0T2aa}e@bR6J6Kc_7gd0d2d46+eGe 8U6Yd}dnacdyd;c:c{d@3teS7e8la20?fhcq13eQflfmdZ8?6{eWd/eZfacT04e$f3b?d b!d(e-d*e5fMa1e/eO13e;dAdaeH9#130Bf2e!f40rd18Of7d6aC6ZdLaadxaedqaC0DfUbofmb.epd}e(fKewfPeye?g2aybae9a`c(b~fX3keebh6t7)0k0,ejfS04fu14fwfxanf cAfLduchdtea8ddVc3aSdkf|042E6+0Xf9a:dmeKfB6DgJ4o0N5.0r2La42L5(2M5X1m2P2O1:1=2O0m1WgT5U1F370N0.0:0=0b04.