Planificarea thread-urilor
1. Introducere
Scop
Scopul acestei lucrri este de prezenta funciile ce pot fi utilizate pentru a stabili
modul de planificare a unui thread, n contextul execuiei concurente a mai
multor thread-uri.
Obiective
Obiectivele ce se dorete a fi atinse prin aceast prezentare sunt:
1. cunoaterea i nelegerea modalitilor de planificare a unui thread
n Linux i a caracteristicilor fiecreia dintre ele;
2. cunoaterea funciilor prin care se stabilete modul de planificare a
thread-urilor;
3. identificarea unor situaii concrete n care posibilitatea de a controla,
pe ct posibil, planificarea thread-urilor poate fi util.
Prezentare general
Planificarea thread-urilor sau proceselor const n strategia folosit de ctre
sistemul de operare pentru a decide la un moment dat care thread trebuie
executat i pentru ct timp. Componenta sistemului de operare care
realizeaz planificarea se numete planificatorul de thread-uri sau procese.
Sistemul de operare Linux folosete un mecanism de planificare bazat pe
prioriti. Fiecrui thread i este asociat o prioritate, fiind ales ntotdeauna
pentru execuie thread-ul cu prioritatea cea mai mare. Corespunztor fiecrei
prioriti se menine o list de thread-uri care candideaz pentru obinerea
procesorului. Rezultatul deciziei de planificare, este controlat prin
implementarea a trei strategii diferite de inserare a thread-urilor n listele de
prioriti. Dintre cele trei strategii, numite politici de planificare, dou sunt
destinate planificrii thread-urilor de prioritate ridicat, ce aparin aplicaiilor
de timp real, iar cea de-a treia este destinat planificrii thread-urilor
aplicaiilor obinuite, de prioritate mic.
Lucrarea de fa descrie cele trei politici de planificare i prezint setul de
funcii destinate stabilirii i modificrii parametrilor ce influeneaz planificarea
unui thread, adic prioritatea i politica de planificare.
1
param
Este
o
structur
prin
care
se
specific
(funcia
pthread_attr_setschedparam) sau n care se obin (funcia
pthread_attr_getschedparam) parametrii politicii de planificare. n
forma actual, structura conine un singur cmp, care este prioritatea
thread-ului, aa cum este ilustrat i mai jos.
struct sched_param{
int sched_priority;
};
Dezavantajul utilizrii unui domeniu de proces pentru planificarea threadurilor este acela c la un moment dat thread-uri ale unui proces pot s
atepte dup eliberarea unui procesor, chiar n situaiile n care thread-uri cu
prioritate mai mic ale altor procese sunt n execuie pe unele procesoare.
Aceasta deoarece dintre thread-urile respectivului proces doar unul este ales
la un moment dat pentru execuie. n cazul domeniul sistem, thread-urile
aceluiai proces pot fi simultan n execuie, att datorit disponibilitii unor
procesoare, ct i datorit faptului c au prioritate mai mare fa de threadurile altor procese.
Funciile de mai jos pot fi folosite pentru stabilirea i obinerea valorii
atributului care determin pentru un thread domeniul de planificare.
#include <pthread.h>
pthread_attr_setscope(
pthread_attr_t *attr, int scope);
pthread_attr_getscope(
pthread_attr_t *attr, int *scope);
4. Proprietatea de motenire
Exist un atribut care ofer posibilitatea ca un thread s moteneasc
atributele de planificare ale thread-ului care l-a creat. Funcia prin care se
seteaz acest atribut se numete pthread_attr_setinheritsched i are
urmtoarea sintax:
#include <pthread.h>
pthread_attr_setinheritsched(
pthread_attr_t *attr, int inherit);
5. Exemplu de utilizare
Codul de mai jos ofer un model de utilizare i testare a principalelor funcii
descrise mai sus pentru stabilirea politicii de planificare i a prioritii unui
thread.
#include <sched.h>
#include <stdlib.h>
void* fcTh(void* arg)
{
int i, policy;
struct sched_param schdPar;
int id = *(int*)arg;
sleep(2);
for (i=1; i<10000; i++) {
pthread_getschedparam(pthread_self(),
&policy, &schdPar);
printf("Thread %d has priority %d\n",
id, schdPar.sched_priority);
printf("Thread %d has policy: ", id);
switch (policy){
case SCHED_OTHER:
printf("SCHED_OTHER\n");
break;
case SCHED_FIFO:
printf("SCHED_FIFO\n");
break;
case SCHED_RR:
printf("SCHED_RR\n");
break;
} // end switch
} // end for
} // end fcTh()
main()
{
pthread_t th1, th2, th3;
pthread_attr_t attr1, attr2, attr3;
struct sched_param schdPar1, schdPar2, schdPar3;
int id1, id2, id3;
printf("The SCHED_FIFO min priority is: %d\n",
sched_get_priority_min(SCHED_FIFO));
printf("The SCHED_FIFO max priority is: %d\n",
sched_get_priority_max(SCHED_FIFO));
printf("The SCHED_RR min priority is: %d\n",
sched_get_priority_min(SCHED_RR));
printf("The SCHED_RR max priority is: %d\n",
sched_get_priority_max(SCHED_RR));
printf("The SCHED_OTHER min priority is: %d\n",
sched_get_priority_min(SCHED_OTHER));
printf("The SCHED_OTHER max priority is: %d\n",
sched_get_priority_max(SCHED_OTHER));
id1 = 1;
pthread_attr_init(&attr1);
pthread_attr_setschedpolicy(&attr1, SCHED_RR);
schdPar1.sched_priority = 10;
pthread_attr_setschedparam(&attr1, &schdPar1);
pthread_create(&th1, &attr1, fcTh, &id1);
id2 = 2;
pthread_attr_init(&attr2);
pthread_attr_setschedpolicy(&attr2, SCHED_RR);
schdPar2.sched_priority = 10;
pthread_attr_setschedparam(&attr2, &schdPar2);
pthread_create(&th2, &attr2, fcTh, &id2);
id3 = 3;
pthread_attr_init(&attr3);
pthread_attr_setschedpolicy(&attr3, SCHED_RR);
schdPar3.sched_priority = 12;
pthread_attr_setschedparam(&attr3, &schdPar3);
pthread_create(&th3, &attr3, fcTh, &id3);
pthread_join(th1, NULL);
pthread_join(th2, NULL);
pthread_join(th3, NULL);
}
10
6. Probleme
1. S se testeze funciile descrise n cadrul lucrrii. Se va folosi ca model
programul C de mai sus. S se stabileasc alternativ diferite politici de
planificare i prioriti ale celor trei thread-uri.
2. n cadrul problemei productor-consumator se cere introducerea unui nou
thread numit garbage-collector care are rolul de eliberare a spaiilor din
buffer coninnd mesaje preluate, dar neeliminate de ctre thread-urile
consumator. Se presupune c thread-urile productor i consumator sunt
programate pentru planificare utiliznd politica SCHED_RR, iar pentru
thread-ul garbage_collector se folosete politica SCHED_OTHER.
3. Se consider un pod pe care se poate circula doar ntr-un singur sens la
un moment dat. n plus, pe pod se pot afla simultan doar MAX_MASINI
maini. O main este reprezentat de un thread, care va executa
procedura Circula(), avnd urmtoarea form:
Circula (int directie)
{
IntraPePod(directie);
TraverseazaPod(directie);
IeseDePePod(directie);
}
12