Sunteți pe pagina 1din 9

Algoritmi de planificare a proceselor

CPU Scheduling este un proces care permite unui proces să


folosească CPU -ul în timp ce execuția unui alt proces este în așteptare
(sau mai bine zis, în starea de așteptare), din cauza indisponibilității
vreunei resurse precum cele de intrare/ieșire, astfel utilizându-se la
maxim CPU -ul. Scopul urmărit de „CPU Scheduling” este acela de a face
sistemul eficient, rapid și sigur.
Oricând CPU -ul este idle (în starea de așteptare), sistemul de
operare trebuie să selecteze unul din procesele din cozile pregătite de a
fi executate. Procesul de selecție este realizat de un planificator pe
termen scurt ( sau, altfel spus, „CPU Scheduler”).
O altă componentă implicată în funcția de CPU Scheduling
este “Dispecerul”. Dispecerul este modulul care permite controlul CPU -
ului la procesele selectate de planificatorul pe termen scurt. Această
funcție implică:
• schimbarea contextului
• schimbarea la modul utilizator
• saltul la locația potrivită în programul utilizator pentru a
reporni acel program în momentul în care a fost lăsat ultima dată.

Tipuri de CPU Scheduling


Deciziile de CPU Scheduling ar putea avea loc în unul din
următoarele patru circumstanțe:
1. Când un proces se schimbă din starea de rulare în cea de
așteptare
2. Când un proces se schimbă din starea de rulare în cea de
pregătire
3. Când un proces se schimbă din starea de așteptare în cea de
pregătire
4. Când un proces se încheie (este terminat).
Originile operației de scheduling preced sistemele computerizate;
Primele abordări au fost luate din disciplina de management a
operațiilor și aplicarea acesteia la calculatoare. Liniile de asamblare și
orice alte operații făcute de om necesită această operație de scheduling
și multe din probleme există aici, incluzând dorința pentru eficiență.
Procesele care rulează în sistem sunt numite și workload.
Determinarea workload -ului este o parte critică de a crea principii de
acțiune.
Presupunerile care se pot face asupra proceselor, numite și job uri,
care rulează în sistem, sunt următoarele:
1. Fiecare job rulează pentru un anume timp prestabilit
2. Toate job -urile sosesc în același timp
3. Odată începute, fiecare job rulează pentru a se termina
4. Toate job -urile pot să utilizeze doar CPU -ul (nu realizează
nicio operație de intrare-ieșire)
5. Run-time -ul fiecărui job este cunoscut.

Pentru a face presupuneri asupra workload -ului, este nevoie și de


compararea diferitelor principii de acțiune (scheduling metric). Un indice
este doar ceva pe care îl folosim pentru a măsura ceva și există un număr
de diferiți indici care au sens în operația de scheduling.
Un astfel de indice este cel de turnaround time. Turnaround time -
ul unui job este definit ca timpul la care job -ul se finalizează minus timpul
la care jobul sosește în sistem.Turnaround time -ul este un indice de
performanță.
Un alt indice este cel de fairness. Performanța și corectitudinea
sunt de obicei în dezacord în ceea ce privește operația de scheduling. Un
scheduler, spre exemplu, ar optimiza performanța, dar la costul de a
preveni câteva job -uri de a rula, așadar scăzând corectitudinea.
Cel mai simplu algoritm de scheduling care se poate implementa
este cel de First In, First Out (FIFO), sau altfel spus First Come, First
Served (FCFS).
FIFO are un număr de proprietăți pozitive. Este ușor de înțeles și
prin urmare ușor de implementat. Și, potrivit presupunerilor, lucrează
destul de bine.
FIFO nu este întotdeauna cea mai bună soluție, această situație
fiind cunoscută sub numele de convoy effect, unde un număr relativ mic
de consumatori potențiali de resurse sunt lăsați în urma unui
consumator major de resurse.
Shortest Job First (SJF) s-a dovedit a fi o abordare foarte simplistă
care rezolvă această problemă. Este o operație “furată” de la cercetările
de operaționalizare și aplicată la job -urile de scheduling din sistemele de
calculatoare. Această nouă disciplină este cunoscută ca Shortest Job
First (SJF) și numele este ușor de memorat deoarece descrie principii
aproape complet : rulează primul job prima dată, apoi următorul cel mai
scurt, și așa mai departe.
Potrivit presupunerilor cum că toate job -urile ajung în același timp,
se poate dovedi că SJF chiar este un algoritm optim privind operația de
scheduling.
Din fericire, există un scheduler care poate preveni un job și decide
să ruleze un alt job, continuându-l pe primul mai apoi. SJF este un
scheduler non-preemptive, deci, suferă de anumite probleme.
Shortest Time-to-Completion First (STCF), față de SJF, adaugă
conceptul de preempțiune la SJF și mai este cunoscut ca și scheduler -ul
Preemptive Shortest Job First (PSJF). În orice moment un nou job intră în
sistem, scheduler -ul STCF determină care din job -urile rămase
(incluzând și noile job -uri) are cel mai puțin timp rămas și îl planifică pe
acela.
Dacă s-ar cunoaște lungimea job -urilor și dacă acele job -uri ar
folosi CPU -ul și singurul indice ar fi turnaround time -ul, STCF ar fi un
principiu foarte bun.
Astfel a apărut conceptul de response time.
Response time se poate defini ca și timpul de când un job ajunge
într-un sistem până când este planificat.
Una dintre cele mai cunoscute abordări de scheduling este cea de
Multi-level Feedback Queue (MLFQ). Scheduler -ul Multi-level Feedback
Queue (MLFQ) a fost descris pentru prima dată în 1962 într-un sistem
numit Compatible Time-Sharing Systems (CTS), și această lucrare,
împreună cu o alta pe Multics, a făcut ca acest sistem să primească
premiul Turing. Scheduler -ul a fost ulterior redefinit dealungul anilor
până la implementarea cu care avem de a face în sistemele moderne de
operare.
Problema fundamentală a MLFQ pe care aceste încearcă să o
adreseze poate fi privită din două unghiuri. Prima dată, ar încerca să
optimizeze turnaround time -ul, care este terminat prin rularea joburilor
scurte, prima dată. Din păcate, sistemul de operare nu știe de obicei cât
de mult un job va rula, precum algoritmi ca SJF (sau STCF) știu. A doua
oară, ar vrea să creeze un sistem care să fie responsive și interactiv
pentru utilizator. Din păcate, algoritmi precum Round Robin reduc
timpul de răspuns, dar nu sunt deloc buni pentru turnaround time.
Problema care se pune este următoarea: de obicei, nu se știe nimic
despre un proces, deci trebuie construit un scheduler care să atingă acest
obiectiv. Scheduler -ul trebuie să învețe, în timp ce sistemul rulează,
caracteristicile job -ului pe care îl rulează, și astfel să facă decizii mai bune
de scheduling.
Pentru a construi un astfel de scheduler, trebuie mai întâi cunoscut
faptul că MLFQ are un număr distinct de stive, fiecare asignată unui
priority level diferit. În orice moment, un job care e pregătit să ruleze se
află pe o singură stivă. MLFQ folosește priorități pentru a decide ce job
ar trebui să ruleze la un anume moment: un job cu o prioritate mai mare
este ales să ruleze.
În mod normal, mai mult de un job ar exista pe o anumită stivă,
deci, au aceiași prioritate.

Regula 1: Dacă Prioritatea (A) > Prioritatea B, A rulează (B nu)


Regula 2: Dacă Prioritatea (A) = Prioritatea (B), A & B rulează
Cheia pentru scheduling -ul MLFQ este ascunsă, astfel, în modul în
care scheduler -ul setează prioritățile. În loc să fie dată o prioritate fixă
pentru fiecare job, MLFQ variază prioritatea unui job bazându-se pe
comportamentul său observabil. Dacă, spre exemplu, un job
abandonează în mod repetat CPU -ul în timp ce așteaptă ca date să fie
introduse de la tastatură, MLFQ va menține prioritatea sa ridicată, căci
așa un proces interactiv s-ar comporta. Dacă, în schimb, un job folosește
CPU -ul intensiv pentru perioade lungi de timp, MLFQ își va reduce
prioritatea.
În acest fel, MLFQ va încerca să învețe despre felul în care procesele
rulează și astfel va folosi istoricul job -ului pentru a prezice
comportamentul său viitor.
MLFQ poate să schimbe nivelul de prioritate al unui job (așadar, și
stiva pe care se află) pe parcursul vieții sale. Pentru a face acest lucru,
trebui avut în vedere workload -ul: un mix de job -uri interactive care
rulează pentru perioade scurte de timp (și care ar abandona periodic CPU
-ul) și câteva joburi care rulează pentru perioade mai lungi și care
folosesc mult timp al CPU -ului, dar unde timpul de răspuns nu este așa
de important. Un algoritm care ajustează prioritatea ar fi următorul:
- când un job intră în sistem, este plasat ca având cea mai mare
prioritate (stiva din vârf)
- daca un job folosește în întregime o bucată de timp în
momentul când rulează, prioritatea sa este redusă (scade cu o stivă)
- daca un job părăsește CPU -ul înainte ca bucata de timp să se
irosească, stă la același nivel de prioritate.

Dacă un proces renunță la procesor înainte să își utilizeze bucata sa


de timp, îl putem menține la același nivel de prioritate.
MLFQ este interesant din următorul motiv: în loc de a se aștepta o
cunoaștere a priori a naturii job -ului, observă execuția unui job și o
prioritizează în mod corespunzător.
Unul dintre abstractizările fundamentale pe care sistemul de
operare le oferă utilizatorilor este procesul. Definiția unui proces, în mod
informal, este destul de simplă: rulează un program. Programul nsăși
doar ocupă spațiu pe disk și este alcătuit dintr-un set de instrucțiuni (și
poate câteva date statice), așteptând să fie rulat. Sistemul de operare
este cel care preia biții și îi rulează, transformând astfel programul în
ceva folositor.
Un sistem obișnuit poate rula ușor zeci sau chiar sute de procese în
același timp. În acest fel sistemul de operare poate rula fără probleme,
CPU -urile fiind disponibile oricând, programele funcționând și ele.
Sistemul de operare crează iluzia existenței mai multor CPU -uri
prin virtualizarea acestuia. Prin rularea unui proces, oprirea lui și rularea
a unui alt proces, și așa mai departe, sistemul de operare crează iluzia că
mai multe CPU -uri virtuale există, când defapt există doar un singur CPU
fizic (sau doar câteva). Această tehnică de bază, cunoscută ca time
sharing, permite utilizatorilor să ruleze în paralel cât de multe procese
au nevoie.
Pentru a implementa virtualizarea CPU -ului și a o face în mod
corespunzător, sistemul de operare va avea nevoie atât de un limbaj
mașină low-level, cât și de o inteligență high-level. Limbajul mașină low-
level mai este numit și mecanism; mecanismele sunt metode low-level
sau protocoale care implementează o anumită funcționalitate de care
este nevoie.
Time sharing -ul este o tehnică de bază folosită de către sistemul
de operare pentru a partaja o resursă. Prin faptul că resursei i se permite
a fi folosită pentru scurt timp de o entitate și apoi de alta, și așa mai
departe, resursa în cauză (spre exemplu, CPU -ul sau un link din rețea)
poate fi folosit de mai mulți utilizatori. Echivalentul time sharing -ului
este space sharing -ul, unde o resursă este divizată (în spațiu) printre cele
care doresc să o folosească.
Switch este operațiunea care oferă abilitatea sistemului de operare
de a opri din rulare un program și a porni un altul pe un anumit CPU.
Controlul acestor mecanisme este deservit de inteligența din
sistemul de operare, sub forma unor principii de acțiuni. Aceste principii
sunt algoritmi care iau anumite decizii în sistemul de operare. Un
principiu programat în sistemul de operare va face această decizie,
utilizând cel mai probabil informația istorică, cunoașterea volumului de
muncă și indici de performanță, pentru a-și lua decizile.
Abstractizarea permisă unui sistem de operare care rulează un
program se numește un proces. Un proces este pur și simplu un program
în execuție; în orice moment, un proces poate fi definit printr-un inventar
al diferitelor părți din sistem pe care le accesează sau afectează în timpul
execuției sale.
Pentru a înțelege exact ce înseamnă un proces, trebuie înțeles și ce
înseamnă machine state: ce poate un program citi sau îmbunătăți în timp
ce rulează.
O componentă ușor de observat a machine state care cuprinde un
proces este memoria sa. Instrucțiunile stau ascunse în memorie; datele
pe care programul care rulează le citește și scrie sunt, de asemenea, în
memorie. Așadar, memoria pe care procesul o poate adresa (numită și
spațiu adresă) este parte din proces.
Din machine state mai fac parte și regiștrii; multe instrucțiuni citesc
sau aduc îmbunătățiri, în mod explicit, la regiștrii și, așadar, sunt evident
importanți în execuția procesului.
Există și câțiva regiștrii speciale care fac parte din machine state.
Spre exemplu, program counter (PC) (uneori numit și instruction pointer
sau IP) indică ce instrucțiune din program este executată curent; similar,
un stack pointer și un frame pointer asociat sunt folosit la administrarea
stivei pentru funcțiile parametru, variabilele locale și adresele returnate.
În cele din urmă, programele accesează frecvent și dispozitive de
stocare
Pentru a putea virtualiza CPU -ul, sistemul de operare trebuie să
partajeze cumva CPU -ul fizic printre multiple procese care rulează în
același timp. Ideea de bază este simplă: un proces trebuie rulat pentru
puțin timp, apoi altul trebuie să facă la fel, și așa mai departe.
Există, totuși, câteva provocări în construirea unei mașinării
virtuale. Prima ar fi performanța: cum ar putea fi implementată
virtualizarea fără a adăuga supraîncărcări excesive la sistem? A doua ar
fi controlul: cum ar putea fi rulat un proces în mod eficient, în timp ce s-
ar menține controlul asupra CPU -ului? Controlul este destul de
important pentru sistemul de operare, deoarece are în responsabilitate
resursele; fără control, un proces ar putea rula mereu și ar lua controlul
asupra mașinii, sau ar putea accesa informații care nu ar trebuie să le
acceseze, în mod normal. Prin obținerea de performanțe înalte, în timp
ce este menținut un control, este așadar unul dintre provocările majore
în crearea unui sistem de operare.
Pentru a face ca un program să ruleze la fel de rapid precum oricine
își dorește, nu în mod surprinzător, dezvoltatorii unui astfel de sistem au
venit cu o tehnică pe care o numesc limited direct execution. Ideea de
„execuție directă” este simplă: un program este pur și simplu rulat direct
pe CPU. Deci, când sistemul de operare dorește să pornească un program
în execuție, crează o intrare de proces pentru acesta în lista de procese,
alocă memorie pentru el, încarcă codul lui în memorie (de pe disk),
localizează punctul său de intrare (în rutina main() sau în ceva similar),
sare la aceasta, și începe rularea codului de la utilizator.
Această abordare aduce, însă, câteva probleme în încercarea de
virtualizare a CPU -ului. Prima este relativ simplă: dacă un program este
pur și simplu rulat, sistemul de operare trebuie să se asigure că
programul nu ar face nimic din ce ar vrea să nu facă, în timp ce ar trebui
să ruleze în mod eficient. A doua problemă care se pune este
următoarea: când un proces este rulat, sistemul de operare l-ar opri din
executare și ar comuta la un alt proces, implementând astfel time
sharing -ul de care este nevoie pentru virtualizarea CPU -ului.
Fără ca anumite limite să fie setate la programele care sunt în curs
de execuție, sistemul de operare nu ar fi în controlul a ceva și, prin
urmare, ar fi „doar o librărie”.
Execuția directă are avantajul implicit de a fi rapidă; programul
rulează nativ pe hardware -ul CPU -ului și astfel se execută rapid la fel de
rapid precum e de așteptat. Dar rularea pe CPU poate introduce o
problemă: procesul ar putea dori să execute o operație restricționată,
precum emiterea unei cereri de intrare-ieșire pe un disk, sau dobândirea
accesului la mai multe resurse precum CPU -ul sau memoria.
O soluție ar fi ca ,pur și simplu, orice proces să fie lăsat să facă ce
dorește în ceea ce privește intrările și ieșirile și alte operații
asemănătoare.
Soluția care trebuie luată, de fapt, este aceea de a introduce un nou
mod de procesare cunoscut ca user mode; codul care rulează în user
mode este restricționat în ceea ce poate face. Spre exemplu, când se
rulează un program în user mode, un proces nu poate emite cereri de
intrare-ieșire; prin această chestiune ar rezulta faptul că procesorul
ridică o excepție; sistemul de operare ar termina procesul, astfel.
În comparație cu user mode este kernel mode, pe care sistemul de
operare (sau kernel -ul) rulează în acesta. În acest mod, codul care
rulează poate face ceea ce îi place, incluzând operații privilegiate precum
cereri de intrare/ieșire și executarea tuturor tipurilor de instrucțiuni
restricționate.
În mod virtual, orice hardware modern oferă abilitatea
programelor utilizator de a realiza un system call. Acesta permite kernel
-ului de a expune cu grijă funcționalități pentru programele utilizator,
precum accesul la sistemul de fișiere, crearea și distrugerea de procese,
comunicarea cu alte procese și alocarea de mai multă memorie.

Bibliografie

[1] "Operating Systems: Three Easy Pieces," 2018. [Online]. Available:


http://pages.cs.wisc.edu/~remzi/OSTEP/.

[2] "StudyTonight," 2018. [Online]. Available: https://www.studytonight.com/operating-system/cpu-


scheduling.

[3] "Wikipedia," 2019. [Online]. Available: https://www.wikipedia.org/.

S-ar putea să vă placă și