Вы находитесь на странице: 1из 40

InstitutoTecnolgicodeMexicali

SistemasdeTiempoReal
Parte4:
POSIXThreads

ArnoldoDazRamrez2006

POSIX
Portable Operating Systems Interfaces (POSIX) es un conjunto evolutivo de
estndares que tienen como principal objetivo el de soportar la portabilidad de las
aplicacionesaniveldecdigofuente
POSIXdefineunainterfazdesistemaoperativobasadoenelsistemaoperativo
UNIX
POSIXnoesunaespecificacinsobreportabilidadaniveldecdigobinariosino
quedefineunaseriedeInterfacesparaProgramasdeAplicacin(API's)enlasque
seespecificaloquelosusuariospuedenrecibirdelsistemaoperativo
ApesardequeoriginalmenteseutilizabaparahacerreferenciaalestndarIEEE
10003.11998, actualmente el trmino POSIX refiere ms correctamente a una
familia de estndares relacionados: el estndar IEEE 1003.n y las partes del
estndarISO/IEC9945,endondeneselnmeroqueindicaunaparteespecficadel
estndar

ArnoldoDazRamrez2006

POSIX

EstndaresPOSIXdeTiempoReal

Estndar

Nombre

IEEEStd1003.1b1993

ExtensionesdeTiempoReal

IEEEStd1003.1c1995

Hilos(threads)

IEEEStd1003.1d1999

ExtensionesdeTiempoRealAdicionales

IEEEStd1003.1j2000

ExtensionesdeTiempoRealAvanzadas

IEEEStd1003.1q2000

Tracing

ArnoldoDazRamrez2006

POSIX

Threads

Unthreadesunflujoindependientedeinstruccionesqueesplanificadopor

elsistemaoperativoparaqueseejecutedemaneraindependiente
Unthreadesmuysimilaraunprocedimientoofuncindeunprograma
Una diferencia con los procedimientos o funciones consiste en que los
threads son ejecutados de manera simultnea e independiente por el
sistemaoperativo
Losthreadssontambinllamadosprocesosligeros(lightweightprocess)ya
quesonsimilaresalosprocesosperoconunasobrecargamuchomenor

ArnoldoDazRamrez2006

POSIXThreads

Threadsyprocesos

ProcesodeUNIX

ArnoldoDazRamrez2006

ThreadsenunprocesodeUNIX

POSIXThreads

Ventajadelusodethreads
Mejordesempeo

Losthreadssoncreadosconunamenorsobrecargaquelosprocesos
Debidoaquelosthreadscompartenelmismoespaciodedirecciones,la
comunicacin entre threads es mucho mas sencilla y eficiente que la
comunicacinentreprocesos
Especializacin: un thread puede esperar eventos de Entradas/Salidas
mientrasotrothreadllevaacabootrasfunciones
Puedeasignarseprioridadalosthreads(tiemporeal)
Manejodeeventosnosncronos:seales,timers,colasdemensajes,etc

ArnoldoDazRamrez2006

POSIXThreads

Ventajadelusodethreads
Enunprograma,lasfuncionescandidatasparatransformarseenthreads

puedenser:
Sebloqueanporintervalosgrandesdetiempo
UtilizanmuchosciclosdeCPU
Debenresponderaeventosnosncronos
Tienemayoromenorimportancia(prioridad)queotrasfunciones
Puedeejecutarseenparaleloconotrasfunciones

ArnoldoDazRamrez2006

POSIXThreads

Modelosdeprogramacinconthreads
Existenalgunosmodelosparaprogramarutilizandothreads:

Manager/Worker.Elthreaddefinidocomoadministradorasignatrabajo
a los threads definidos como trabajadores. Generalmente, el
administrador recibe los datos de entrada, crea el thread que los
procesaryleasignaeltrabajoarealizar
Pipeline.Untrabajoesdividoenunaseriedesuboperaciones,cada
unadelascualesesejecutadaporunthread
Peer.SimilaralManager/Worker,conladiferenciadequeunavezque
el administrador a creado todos los threads, participa tambin en el
trabajo

ArnoldoDazRamrez2006

POSIXThreads

POSIXThreads
ElAPIdePOSIXThreadsestadefinidoenelestndarIEEEStd1003.1c

1995
LasfuncionesqueconformanelAPIdePthreads(POSIXThreads)estn
divididasendiferentescategoras,entrelasquedestacan:
Administracin
Planificacin
Sincronizacin(mutex)
Variablesdecondicin
Seales

ArnoldoDazRamrez2006

POSIXThreads

APIparaPThreads
Prefijodelafuncin

Grupofuncional

pthread_

Administracindethreads

pthread_attr

Objetosdeatributos

pthread_mutex

Mutex

pthread_mutexattr

Atributosdemutex

pthread_cond

Variablesdecondicin

pthread_condattr

Atributosdevariablesdecondicin

pthread_key

Llavesdedatosespecficosdeunthread

ArnoldoDazRamrez2006

POSIX

Ejemplo(hola.c)
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#defineNUM_THREADS 5
void*PrintHello(void*threadid)
{
printf("\n%d:HolaMundo!\n",threadid);
pthread_exit(NULL);
}

intmain(intargc,char*argv[])
{
pthread_tthreads[NUM_THREADS];
intrc,t;
for(t=0;t<NUM_THREADS;t++){
printf("Creandoelthread%d\n",t);
rc=pthread_create(&threads[t],NULL,PrintHello,(void*)t);
if(rc){
printf("ERROR;elcodigoderetornodelafuncionpthread_create()es%d\n",rc);
exit(1);
}
}
pthread_exit(NULL);

ArnoldoDazRamrez2006

POSIX

Creacinyterminacindethreads
Creacindeunthread:
intpthread_create(pthread_t*thread,
constpthread_attr_t*attr,
void*(*start_routine)(void*),
void*arg)
La funcin pthread_create() crear un nuevo thread en un proceso, con los atributos
especificadosenattr.SiattresNULL,seutilizarnlosvaloresdeatributospordefecto.Sise
completaconxito,lafuncinpthread_create()almacenarelidentificador(ID)delthreaden
ladireccinalaquehacereferenciathread.
El thread se crea ejecutando la rutina start_routine() con argumento arg. Si la rutina
start_routine() retorna, el efecto ser similar al de una llamada implcita a pthread_exit(),
utilizandoelvalorderetornodestart_routine().
Elestadodelassealesdelnuevothreadserelsiguiente:
Seheredarlamscaradesealesdelthreadcreador
Elconjuntodesealespendientesdelnuevothreadestarvaco

Siseejecutaconxito,lafuncinpthread_create()retornarelvalordecero

ArnoldoDazRamrez2006

POSIXThreads

Creacinyterminacindethreads
Terminacindeunthread:
intpthread_exit(void*value_ptr)
La funcin pthread_exit() terminar la ejecucin del thread que haga la llamada y hace
disponibleelvalorvalue_ptrparacualquierjoinconxitoconelthreadquehacelallamada.

Iniciodeatributosdeunthread:
intpthread_attr_init(pthread_attr_t*attr)
Lafuncinpthread_attr_init()inicializarelobjetodeatributosattrdelthreadconlosvalores
pordefectoutilizadosenunaimplementacin

ArnoldoDazRamrez2006

POSIXThreads

Creacinyterminacindethreads
Destruccindeatributosdeunthread:
intpthread_attr_destroy(pthread_attr_t*attr)
Lafuncinpthread_attr_destroy()destruirelobjetodeatributosattrdelthreadconvalores
nodefinidosenunaimplementacin.Unobjetodeatributosdestruidoconestafuncinpodr
serinicializadoposteriormenteconlafuncinpthread_attr_init()

ArnoldoDazRamrez2006

POSIXThreads

Pasandoargumentosalosthreads
Al crear un thread utilizando la funcin pthread_create() es posible pasar un
argumentoalarutinadelthread(start_routine)
Todoargumentodebepasarseporreferenciayhaciendocasta(void*)
Debetenersecuidadoalpasarargumentosalthreadyaqueelcontenidodela
direccindememoriapuedecambiarantesdequeelthreadlaaccese
EjemploargumentosThread.c:
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#defineNUM_THREADS

char*messages[NUM_THREADS];

structthread_data
{
int thread_id;
intsum;
char*message;
};

ArnoldoDazRamrez2006

POSIXThreads

Pasandoargumentosalosthreads
Ejemplo(continuacin):
structthread_datathread_data_array[NUM_THREADS];
void*PrintHello(void*threadarg)
{
inttaskid,sum;
char*hello_msg;
structthread_data*my_data;
sleep(1);
my_data=(structthread_data*)threadarg;
taskid=my_data>thread_id;
sum=my_data>sum;
hello_msg=my_data>message;
printf("Thread%d:%sSuma=%d\n",taskid,hello_msg,sum);
pthread_exit(NULL);
}

ArnoldoDazRamrez2006

POSIXThreads

Pasandoargumentosalosthreads
Ejemplo(continuacin):
intmain(intargc,char*argv[])
{
pthread_tthreads[NUM_THREADS];
int*taskids[NUM_THREADS];
intrc,t,sum;
sum=0;
messages[0]="Espanol:Holaalmundo!";
messages[1]="Frances:Bonjour,lemonde!";
messages[2]="Ingles:HelloWorld!";
messages[3]="Aleman:GutenTag,Welt!";
messages[4]="Japones:Sekaiekonnichiwa!";

ArnoldoDazRamrez2006

POSIXThreads

Pasandoargumentosalosthreads
Ejemplo(continuacin):
for(t=0;t<NUM_THREADS;t++){
sum=sum+t;
thread_data_array[t].thread_id=t;
thread_data_array[t].sum=sum;
thread_data_array[t].message=messages[t];
printf("Creandoelthread%d\n",t);
rc=pthread_create(&threads[t],NULL,PrintHello,(void*)
&thread_data_array[t]);
if(rc){
printf("ERROR;elcodigoderetornodepthread_create()es%d\n",rc);
exit(1);
}
}
pthread_exit(NULL);
}//finmain()

ArnoldoDazRamrez2006

POSIXThreads

Threadsperidicos
Algunasaplicacionessebeneficiansilosthreadstieneuncomportamiento

peridico
Laestructuradelcdigodeunthreadperidicopuedesercomosemuestra
acontinuacin:
intthread_code(...){
...
ejecutarfuncionadeinicializacin
...
while(1){
suspenderthreadhastasiguienteperiodo
ejecutarfuncionesperidicas
...
}
}

ArnoldoDazRamrez2006

POSIXThreads

Threadsperidicos
Funcionesdeinicializacin
Funcionesperidicas

T1
0

1
0

1
2

1
4

1
6

1
0

1
2

1
4

1
6

1
0

1
2

1
4

1
6

T2

T3

instantedesincronizacin

ArnoldoDazRamrez2006

POSIXThreads

Implementacindethreadsperidicos
EjemploperiodicosThread.c:
#include<time.h>
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#defineNUM_THREADS
structtimespecperiod;

void*thread_code(void*t)
{
inttaskno=(int)t;
structtimespecnext;
printf("\n%d:Funcionesdeinicio",taskno);
clock_gettime(CLOCK_REALTIME,&next);

while(1){
timespec_add(&next,&period);
clock_nanosleep(CLOCK_REALTIME,TIMER_ABSTIME,
&next,NULL);
printf("\n%d:Funcionesperiodicas",taskno);
}
pthread_exit(NULL);
return0;
}

ArnoldoDazRamrez2006

POSIXThreads

Implementacindethreadsperidicos
Ejemplo(continuacin):
intmain(intargc,char*argv[])
{
pthread_tthreads[NUM_THREADS];
intrc,t;
period.tv_nsec=50000;
period.tv_sec=0;
for(t=0;t<NUM_THREADS;t++){
printf("Creandoelthread%d\n",t);
rc=pthread_create(&threads[t],NULL,thread_code,(void*)t);
if(rc){
printf("ERROR;elcodigoderetornodepthread_create()es%d\n",rc);
exit(1);
}
}
pthread_exit(NULL);
}

ArnoldoDazRamrez2006

POSIXThreads

Implementacindethreadsperidicos
Definiciones(rtlinux/include/time.h):
#defineNSEC_PER_SEC

1000000000L

#definetimespec_normalize(t){\
if((t)>tv_nsec>=NSEC_PER_SEC){\
(t)>tv_nsec=NSEC_PER_SEC;\
(t)>tv_sec++;\
}elseif((t)>tv_nsec<0){\
(t)>tv_nsec+=NSEC_PER_SEC;\
(t)>tv_sec;\
}\
}
#definetimespec_add(t1,t2)do{\
(t1)>tv_nsec+=(t2)>tv_nsec;\
(t1)>tv_sec+=(t2)>tv_sec;\
timespec_normalize(t1);\
}while(0)

ArnoldoDazRamrez2006

POSIXThreads

Joiningthreads
Unin(join)deunthread:
intpthread_join(pthread_t*thread,void**value_ptr)
Lafuncinpthread_join()suspenderlaejecucindelthreadquehacelallamada,hastaque
el thread destino termine. El valor que pase el thread destino con la funcin pthread_exit()
estardisponibleenlalocalidaddememoriaalaquehacereferenciavalue_ptr.

Joiningesunmecanismoquepermitelasincronizacindethreads

Thread
Maestro

pthread_create()

Thread
Trabajador

ArnoldoDazRamrez2006

pthread_join()

hace
trabajo

pthread_exit()

POSIXThreads

Joiningthreads
Cuando se crea un thread, uno de sus atributos define si el thread es
joinableodetached
Siescreadocomodetached,nopodrutilizarselafuncinpthread_join()

parasincronizarsuterminacin
Para crear explcitamente un thread como joinable o detcahed, el
argumento attr de la funcin pthread_create() debe utilizarse, siguiendo los
siguientespasos:
Declararunobjetodeatributosdelthread,deltipopthread_attr_t
Inicializarelobjetodeatributosconlafuncinpthead_attr_init()
Conlafuncinpthread_attr_setdetachstate(),definirelestadodetach
delthread
Liberarrecursosusandolafuncinpthread_attr_destroy()

ArnoldoDazRamrez2006

POSIXThreads

Detachingthreads
Separar(detach)unthread:
intpthread_detach(pthread_t*thread)
Lafuncinpthread_detach()indicaralaimplementacin(so)quelosrecursosdelthread
(memoria)especificadoporthreadpuedenserreclamadoscuandoelthreadtermina

Sehasugeridoqueestafuncinnoesnecesariayaquepuededefinirseel

estado detach del thread con la funcin pthread_attr_setdetachstate(). Sin


embargo,POSIXjustificaestafuncindebidoalassiguientessituaciones:
En un manejador (handler) de cancelacin para pthread_join() es
necesariayaquepermiteliberarlosrecursosdeunthreadqueesperaa
queotrotermineutilizandolafuncinpthread_join()

Paraliberarlosrecursosdelthreadinicialyquehacreadoelrestode
losthreads

ArnoldoDazRamrez2006

POSIXThreads

Implementacindethreadsperidicos
EjemplojoinThread.c:
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#defineNUM_THREADS

void*HacerTrabajo(void*null)
{
inti;
doubleresult=0.0;
for(i=0;i<1000000;i++)
{
result=result+(double)random();
}
printf("ResultadodelThread=%e\n",result);
pthread_exit((void*)0);
}
intmain(intargc,char*argv[])
{
pthread_tthread[NUM_THREADS];
pthread_attr_tattr;
intrc,t,status;

ArnoldoDazRamrez2006

POSIXThreads

Implementacindethreadsperidicos
Ejemplo(continuacin):
/*Inicializaryestablecerelatributodetacheddelthread*/
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);
for(t=0;t<NUM_THREADS;t++)
{
printf("Creandothread%d\n",t);
rc=pthread_create(&thread[t],&attr,HacerTrabajo,NULL);
if(rc)
{
printf("ERROR:elcodigoderetornodepthread_create()es%d\n",rc);
exit(1);
}
}

ArnoldoDazRamrez2006

POSIXThreads

Implementacindethreadsperidicos
EjemplojoinThread.c:

/*Seliberaobjetodeatributosyseesperaporelrestodelosthreads*/
pthread_attr_destroy(&attr);
for(t=0;t<NUM_THREADS;t++)
{
rc=pthread_join(thread[t],(void**)&status);
if(rc)
{
printf("ERROR:elcodigoderetornodepthread_join()es%d\n",rc);
exit(1);
}
printf("Secompletoeljoinconelthread%dyconestado=%d\n",t,status);
}
pthread_exit(NULL);
}

ArnoldoDazRamrez2006

POSIXThreads

Polticadeplanificacinyprioridaddelosthreads
Planificacinunthread:
intpthread_attr_setschedpolicy(pthread_attr_t*attr,intpolicy)
Lafuncinpthread_attr_setschedpolicy()establecerlapolticadeplanificacinpolicyenel
objetodeatributosattrdeunthread.LaspolticassoportadassonSCHED_FIFO,SCHED_RR
ySCHED_OTHER

Ejemplo de definicin de la poltica de planificacin y prioridad de un


thread:
pthread_attr_tattr;
structsched_paramp;

pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr,SCHED_FIFO);
p.sched_priority=10;
pthread_attr_setschedparam(&attr,&p);
....

ArnoldoDazRamrez2006

POSIXThreads

Funcionesadicionales
Threadactual:
intpthread_self()
Lafuncinpthread_self()retornarelidentificador(ID)delthreadquehagalallamada

Comparacindethreads:
intpthread_equal(pthread_tt1,pthread_tt2)
La funcinpthread_equal() comparar losidentificador (ID)delos threads t1y t2. Si son
iguales,lafuncinretornarunvalordiferentedecero;sisondiferentesretornarcero.

ArnoldoDazRamrez2006

POSIXThreads

Sincronizacin
Para controlar el acceso a las secciones crticas, POSIX utiliza un mecanismo
similaralossemforosbinarios
Los semforos binarios han sido nombrados por POSIX como mutex (mutual
exclusion)
Unavariabledetipomutexactacomounbloqueo(lock)paraprotegerrecursos
compartidos
nicamenteunthreadpuedebloquearunrecursoenuninstantedeterminado
POSIXhadefinidolossiguientesprotocolosdeaccesoarecursos(extensiones
detiemporeal):
PTHREAD_PRIO_NONE
PTHREAD_PRIO_INHERIT
PTHREAD_PRIO_PROTECT

ArnoldoDazRamrez2006

POSIXThreads

Funcionesrelacionadasconmutex
pthread_mutex_destroy,pthread_mutex_init

destruyeeinicializaunmutex

pthread_mutex_getprioceiling,pthread_mutex_setprioceiling

obtieneyestablecelatechodeprioridad
deunmutex(RT)

pthread_mutex_init

inicializaunmutex

pthread_mutex_lock,pthread_mutex_trylock,
pthread_mutex_unlock

bloquea(lock)yliberaunmutex

pthread_mutex_setprioceiling

cambiaeltechodeprioridaddeunmutex
(RT)

pthread_mutex_timedlock

bloquea(lock)unmutex(ADVANCEDRT)

pthread_mutex_trylock,pthread_mutex_unlock

blqueayliberaunmutex

pthread_mutexattr_destroy,pthread_mutexattr_init

destruyeeinicialuzaunobjetode
atributosdeunmutex

pthread_mutexattr_getprioceiling,
pthread_mutexattr_setprioceiling

obtieneyestableceelatributoprioceiling
deunobjetodeatributosdeunmutex(RT)

ArnoldoDazRamrez2006

POSIXThreads

Funcionesrelacionadasconmutex
pthread_mutexattr_getprotocol,
pthread_mutexattr_setprotocol

obtieneyestableceelatributoprotocol
delobjetodeatributossdeunmutex(RT)

pthread_mutexattr_getpshared,
pthread_mutexattr_setpshared

obtieneyestableceelatributoprocessshared

pthread_mutexattr_gettype,
pthread_mutexattr_settype

obtieneyestableceelatributotype

pthread_mutexattr_init

inicializaunobjetodeatributosdeunmutex

pthread_mutexattr_setprioceiling

estableceelatributoprioceilingdeunobjeto
deatributosdeunmutex(RT)

pthread_mutexattr_setprotocol

estableceelatributoprotocoldeunobjeto
deatributosdeunmutex(RT)

pthread_mutexattr_setpshared

estableceelatributoprocessshared

pthread_mutexattr_settype

estableceelatributotype

ArnoldoDazRamrez2006

POSIXThreads

Ejemplo
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
/*
Lasiguienteestructuracontienelainformacinnecesariaparapermitirquelafuncindotprodaccese
asusdatosdeentradaypongasuresultadoenlaestructura
*/
typedefstruct
{
double*a;
double*b;
doublesum;
intveclen;
}DOTDATA;

ArnoldoDazRamrez2006

POSIXThreads

Ejemplo
/*Sedefinenlasvariablesglobalesyunmutex*/
#defineNUMTHRDS4
#defineVECLEN100

DOTDATAdotstr;
pthread_tcallThd[NUMTHRDS];
pthread_mutex_tmutexsum;
/*
Lafuncindotprodseactivacuandosecreaelthread.Losdatosdeentradaseobtienendela
estructuradetipoDOTDATAylosresultadosdelafuncinseescribenenlaestructura.Cuandose
creaunthreadsepasaunargumentoalafuncin(elnmerodethread),yelrestodelainformacin
seobtienedelaestructura.Deestamaneraelprocesosebeneficiadelusodemltipleshilos.
*/
void*dotprod(void*arg)
{
inti,start,end,offset,len;
doublemysum,*x,*y;
offset=(int)arg;

ArnoldoDazRamrez2006

POSIXThreads

Ejemplo
len=dotstr.veclen;
start=offset*len;
end=start+len;
x=dotstr.a;
y=dotstr.b;
/*Sellevaacaboelproductoyseasignaelresultadoalavariablecorrespondientedelaestructura*/
mysum=0;
for(i=start;i<end;i++)
{
mysum+=(x[i]*y[i]);
}
/*Sebloqueaelmutexamtesdeactualizarlosdatosenlaestructuracompartida,yseliberadespus*/
pthread_mutex_lock(&mutexsum);
dotstr.sum+=mysum;
pthread_mutex_unlock(&mutexsum);
pthread_exit((void*)0);
}

ArnoldoDazRamrez2006

POSIXThreads

Ejemplo
/*
Elprogramacrealosthreads,queharntodoeltrabajo,eimprimirelresultado.Antesdecrearlos
threads,secreanlosdatosdeentrada.Debidoaquelosthreadsutilizan(comparten)lamisma
estructurasehacenecesariolautilizacindeunmutex.Lafuncin(thread)main()debeesperaraque
losthreadsconcluyanparaimprimirelresultado.
*/
intmain(intargc,char*argv[])
{
inti;
double*a,*b;
intstatus;
pthread_attr_tattr;
/*Seasignaalmacenamientoyseinicializanvalores*/
a=(double*)malloc(NUMTHRDS*VECLEN*sizeof(double));
b=(double*)malloc(NUMTHRDS*VECLEN*sizeof(double));

ArnoldoDazRamrez2006

POSIXThreads

Ejemplo

for(i=0;i<VECLEN*NUMTHRDS;i++){
a[i]=1;
b[i]=a[i];
}
dotstr.veclen=VECLEN;
dotstr.a=a;
dotstr.b=b;
dotstr.sum=0;
pthread_mutex_init(&mutexsum,NULL);

/*Secreanlosthreads*/
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);

ArnoldoDazRamrez2006

POSIXThreads

Ejemplo
for(i=0;i<NUMTHRDS;i++)
{
/*Cadathreadtrabajaconunconjuntodiferentededatos.Eloffsetestespecificadopori.El
tamaodelosdatosparacadathreadseespecificaenVECLEN*/
pthread_create(&callThd[i],&attr,dotprod,(void*)i);
}
pthread_attr_destroy(&attr);
for(i=0;i<NUMTHRDS;i++){
pthread_join(callThd[i],(void**)&status);
}

printf("Sum=%f\n",dotstr.sum);
free(a);
free(b);
pthread_mutex_destroy(&mutexsum);
pthread_exit(NULL);
}

ArnoldoDazRamrez2006

POSIXThreads

Вам также может понравиться