You are on page 1of 14

PROGRAMACIN

DE SISTEMAS EMPOTRADOS Y DE TIEMPO REAL

Prctica 2
El tiempo. Diseo de un cronmetro



Mario Piero de Mier


Toms Ruz Rodrguez
Eduardo Bailn Martnez


2 Prctica 2 PSETR - El tiempo. Diseo de un cronmetro


Introduccin

La presente prctica prctica tiene como objetivos la medicin del tiempo en
aplicaciones sobre sistemas operativos POSIX, el diseo de un cronmetro de alta precisin y
la medicin del WCET (Worst Case Execution Time).
Se va a medir el tiempo en dos sistemas diferentes. El primero de ellos ser el sistema
empotrado del laboratorio (sistema operativo QNX), el cual est basado en una arquitectura
x86 con un microprocesador Via Eden de 667 MHz y 256 MB de memoria RAM. Compararemos
los resultados con los obtenidos mediante una mquina con sistema operativo Linux.
Se utilizarn llamadas al sistema definidas en las normas POSIX para medir el tiempo y definir
nuestras propias funciones a partir de las mismas con el objetivo de facilitar la lectura del
tiempo por parte del usuario.

Realizacin prctica

Ejercicio 1

En este apartado se va a compilar y ejecutar el programa ejemplo medidatiempo.c
sobre dos mquinas con distintos sistemas operativos POSIX (QNX y Linux) para medir el
tiempo que tarda en ejecutarse un determinado comando. En este caso se pasar como
argumento "ls -la" , y se obtendr el tiempo que tarda en ejecutarse. Este proceso se realizar
tres veces en cada una de las mquinas.
Es importante tener en cuenta que se va a hacer uso de la llamada al sistema clock_gettime(),
la cual devuelve una estructura de tipo timespec, que ofrece la posibilidad de medir el tiempo
con una resolucin terica de 1ns:
struct timespec {

time_t tv_sec;

log
tv_nsec;
};

Sin embargo, no se medir el tiempo con esta resolucin (lmite terico), sino que ser
necesario conocer el tiempo que transcurre entre dos instantes de reloj consecutivos, es decir,
la granularidad del sistema.

Teniendo presente lo anterior, compilamos medidatiempo.c la siguiente forma:
gcc medidatiempo.c -o medidatiempo (QNX)
gcc medidatiempo.c -o medidatiempo -lrt (Linux)

3 Prctica 2 PSETR - El tiempo. Diseo de un cronmetro



(NOTA:Es necesario incluir "-lrt" cuando se compila en la mquina Linux para linkar las libreras
de tiempo real). De esta forma se genera el ejecutable medidatiempo, mediante el cual
podremos obtener el tiempo que tarda en ejecutarse un determinado comando (en nuestro
caso "ls -la"), de la siguiente forma:
./medidatiempo ls -la

Realizando esta medida tres veces en cada uno de los sistemas, se obtienen los siguientes
resultados:

Sistema Operativo Medida 1 (s)
Medida 2 (s)
Medida 3 (s)
QNX

30336.7826

30785.3754

30314.4388

Linux

2386.4070

2446.9990

2396.7960


La mquina (sistema empotrado) con sistema operativo QNX de versin 6.3.0 est basada en
una arquitectura x86 con un microprocesador Via Eden de 667 MHz y 256 MB de memoria
RAM, dispone de unos recursos hardware ms pobres que la mquina Linux utilizada, por
tanto es lgico que el tiempo de ejecucin sea mayor en el caso del sistema empotrado con
sistema operativo QNX.

Ejercicio 2

Como se ha descrito anteriormente, la granularidad (tiempo que transcurre entre dos
instantes de reloj consecutivos) influye en la medida del tiempo realizada. La resolucin
terica es de 1ns, sin embargo en el apartado anterior se han obtenido medidas de tiempo con
una granularidad mayor (1ms).
En este apartado se pretende ver el efecto que tiene la granularidad sobre las medidas de
tiempo. Si cambiamos la granularidad del sistema a 100 s, los resultados de las medidas de
tiempo realizadas en la mquina de sistema operativo QNX cambian de la siguiente manera:
Sistema Operativo

Medida 1 (s)

Medida 2 (s)

Medida 3 (s)

QNX (granularidad: 1ms)

30336.7826

30785.3754

30314.4388

QNX (granularidad: 100 s)

31940.4893

32457.0663

32182.1964


Observamos que al utilizar una granularidad menor se obtiene un tiempo de ejecucin mayor.
Esto es debido a que estamos cargando demasiado el sistema midiendo el tiempo con
demasiada regularidad, consumiendo demasiados recursos de CPU y haciendo que el tiempo
de ejecucin de las tareas se incremente. Es por ello que debemos elegir una granularidad
adecuada para que se pueda medir el tiempo con la mayor precisin posible sin consumir
excesivos recursos.

4 Prctica 2 PSETR - El tiempo. Diseo de un cronmetro



Ejercicio 3

En este ejercicio se ha optado por copiar directamente el cdigo de ambos archivos. Se
ha colocado el archivo crono.h que ha sido incluido en crono.c para la mejora de que todo est
organizado en paquetes, aunque a la hora de compilar el archivo, se tendr que aadir en la
lnea el archivo de dependencias para que el proceso se lleve a cabo correctamente.

Ejercicio 4

Se procede modificando el programa medidatiempo.c, y se crea un nuevo programa
que se llamar medidatiempo2.c de forma que se utiliza el cronmetro implementado en el
apartado anterior. Una vez creado, se realizan las pruebas oportunas para comprobar los
resultados del ejercicio 1 y ver as la precisin del programa modificado. Se realiza la prueba
con el comando ls la como en el apartado 1. Los resultados obtenidos son los siguientes:

Sistema Operativo

Medida 1 (s)

Medida 2 (s)

Medida 3 (s)

QNX

31445.2453

31223.8502

31114.7236

Linux

2745.3320

26536.7085

2813.2388

Por la misma razn que en el ejercicio 1, el sistema empotrado con QNX dispone de unos
recursos hardware ms pobres, por lo que el tiempo de ejecucin es mayor que en el entorno
Linux utilizado. La similitud en las medidas del ejercicio 1 y este, nos sugieren que la
elaboracin del cdigo es la correcta en ambos casos.

Ejercicio 5

En este ejercicio se va a comprobar el funcionamiento del programa medidaWCET.c
que hay que modificar pertinentemente de forma que utilice nuestro cronmetro diseado
previamente. El programa har una medida de tiempos de una funcin blanco, realizndose
medidas de tiempo variando el nmero de iteraciones. El programa blanco.c consta de un
algoritmo que realiza muchas operaciones matemticas y que permite variar el nmero de
iteraciones. A modo de ejemplo, si establecemos un nmero de iteraciones de 1000, se
obtiene lo siguiente en la mquina QNX:
Sistema Operativo

Resolucin del
reloj (ns)

QNX

999847

Tiempo
promedio (1
iteracin) (s)
927.858016

Tiempo total
(s)
927858.016000


Se puede comprobar simplemente cambiando el nmero de iteraciones, que, a medida que
ste aumenta, crece el tiempo total de ejecucin del programa.

5 Prctica 2 PSETR - El tiempo. Diseo de un cronmetro


Ejercicio 6
Por ltimo, en este ejercicio vamos a analizar la ejecucin del programa anterior
medidaWCET.c sobre distintas mquinas y distintos sistemas operativos, para estudiar cmo
afecta la carga del sistema en la ejecucin de una orden dependiendo de la mquina y del
sistema operativo. Para ello se realiza mediante el programa carga.c, tantas veces como sea
necesario, ejecutndose en terminales diferentes.
De este modo, para carga baja no se har ninguna llamada al programa carga.c, para el caso de
media carga se cargarn 2 procesos en el empotrado y 10 en el porttil con sistema operativo
Linux, y por ltimo, para carga alta, 4 procesos en el empotrado y 20 en el porttil. Por ltimo
aadir, que para el caso del porttil el nmero de ejecuciones del programa podra ser incluso
mayor debido a que el rendimiento en general no se ve afectado, aunque como se ver a
continuacin s lo ser para el ejemplo.
A continuacin se realizan las pruebas oportunas sobre los distintos sistemas y los resultados
obtenidos son los que se presentan a continuacin:
S.O Anfitrin 1 realizacin (us) 2 realizacin (us) 3 realizacin (us) Media (us)
QNX
927857.816
926858.169
928857.863
927858.016
Linux
47792.965
39878.998
44823.552
44164.838
Tabla Comparativa de resultados de 'ls-la' en mquinas QNX y Linux con baja carga

S.O Anfitrin 1 realizacin (us) 2 realizacin (us) 3 realizacin (us) Media (us)
QNX
2798571.753
2794572.365
2792572.671
2795238.930
Linux
188694.279
357256.648
258286.676
268079.201
Tabla Comparativa de resultados de 'ls-la' en mquinas QNX y Linux con media carga

S.O Anfitrin 1 realizacin (us) 2 realizacin (us) 3 realizacin (us) Media (us)
QNX
4699280.900
4558302.473
4601295.894
4619626.422
Linux
659953.687
497278.187
598525.638
585252.504
Tabla Comparativa de resultados de 'ls-la' en mquinas QNX y Linux con alta carga

Como era de esperar, al aumentar la carga en los sistemas, el tiempo de ejecucin aumenta
proporcionalmente. Tambin se aprecia que el pc sobre el que se ejecuta Linux, es mucho ms
rpido que el sistema QNX.

ANLISIS DE RESULTADOS
En el ejercicio 1 y 2 se vio cmo medir el tiempo que tardaba un sistema en ejecutar un
comando en distintos equipos mediante una misma implementacin de cdigo, ya que ambos
sistemas eran compatibles con el estndar POSIX. Tambin se vio que el tiempo que tardaba el
sistema empotrado con QNX era superior que en el PC convencional.
En el ejercicio 3 y 4 se logr la implementacin de un cronmetro de altas prestaciones para la
medicin de tiempos de ejecucin, y se comprob que funcionaba correctamente mediante
algunas de pruebas con getMillis y getMicros. Gracias a que este cronomtro se ha

6 Prctica 2 PSETR - El tiempo. Diseo de un cronmetro



implementado siguiendo las normas del estndar POSIX podremos utilizarlo para otros
proyectos o en otros sistemas que cumplan con dicho estndar. Dichos programas se
encuentran en el ANEXO de la presente.
Por ltimo, para el ejercicio 6 se vio que a medida que aumentaba el nmero de procesos en
segundo plano, el tiempo empleado por el sistema en ejecutar un comando aumentaba,
siendo el tiempo mayor en el sistema empotrado con QNX que en el pc convencional. Aunque
los resultados se muestren en nanosegundos y pueda parecer que no es de importancia la
diferencia de tiempo, en un sistema de tiempo real puede darse situaciones crticas. Para
mostrar los resultados de forma ms visual se presenta la siguiente grfica comparativa:
5000000

Tiempo de ejecucin (nanosegundos)

4500000
4000000
3500000
3000000
2500000

QNX

2000000

Linux

1500000
1000000
500000
0
Baja

Media

Alta

Anexo: Cdigos fuente de los programas utilizados.


crono.h
/***************************************************************
****************
*
*
Practica #2: Cronometro POSIX. Definicin de las funciones
del cronometro POSIX
*
*
Autor: J.A. Holgado
*
Ultima modificacion: 29/03/15
*
Plataforma: POSIX
*
Asignatura: Desarrollo de Sistemas de Tiempo Real
*
Departamento: Lenguaje y Sistemas Informatico
*
Universidad de Granada
*
****************************************************************
***************/
#ifndef CRONO_H_
#define CRONO_H_
#include <time.h>

//clock_gettime()

7 Prctica 2 PSETR - El tiempo. Diseo de un cronmetro



//Define las constantes de tiempo
#define NANO_PER_SECOND
1000000000L
#define MICRO_PER_SECOND
1000000L
#define MILI_PER_SECOND
1000L
#define MICRO_PER_NANO
#define MILI_PER_NANO
#define SECOND_PER_NANO

1e-3
1e-6
1e-9

//Registra la referencia de tiempo


int start(void);
//Devuelve el intervalo de tiempo transcurrido en una estructura
timespec
int elapse2timespec(struct timespec *timeInterval);
// Devuelve el intervalo de tiempo transcurrido en millis
int elapse2millis(double *dIntervalMs);
// Devuelve el intervalo de tiempo transcurrido en millis
int elapse2micros(double *dInterval);
//devuelve los microsegundos de un tiempo en timespec
double getMicros(struct timespec *t1);
//devuelve los millisegundos de un tiempo en timespec
double getMillis(struct timespec *t1);
//devuelve los segundos de un tiempo en timespec
double getSeconds(struct timespec *t1);
//devuelve el tiempo en timespec de un tiempo en segundos
struct timespec getTimespec(double *sec);
//Calcula la diferencia de tiempos con estructuras timespec
struct timespec timeDifference(struct timespec *t1, struct
timespec *t2);
// Obtiene la suma de tiempos con estructura timespec
struct timespec timeSum(struct timespec *t1, struct timespec
*t2);
#endif //CRONO_H_

crono.c
/***************************************************************
****************
*
*
Practica #2: Cronometro POSIX. Implementacion de las
funciones del cronometro POSIX
*

8 Prctica 2 PSETR - El tiempo. Diseo de un cronmetro



*
Autor: J.A. Holgado
*
Ultima modificacion: 29/03/15
*
Plataforma: POSIX
*
Asignatura: Desarrollo de Sistemas de Tiempo Real
*
Departamento: Lenguaje y Sistemas Informatico
*
Universidad de Granada
*
****************************************************************
***************/
#include "crono.h"
//Variable global para registrar el instante de referencia y el
instante de parada temporal
struct timespec timeReference;
////////////////////////////////////////////////////////////////
/////////
// Funcion start: Inicia el cronometro marcando el tiempo
inicial
int start(void)
{
//******Marca el instante de referencia del cronometro con
clock_gettime utilizando timeReference
clock_gettime(CLOCK_REALTIME, &timeReference); //marcamos
tiempo inicial
return 0;
}
////////////////////////////////////////////////////////////////
/////////
// Funcion elapse2timespec: Devuelve el intervalo de tiempo
transcurrido
// en una estructura timespec
// Param1: (OUT) Intervalo de tiempo en estructura timespec
// Return: Codigo error de la operacion (0 no hay error)
int elapse2timespec(struct timespec *timeInterval)
{
struct timespec timeElapse;
//***************
//******Marca el instante de referencia del cronometro con
clock_gettime utilizando timeElapse
clock_gettime(CLOCK_REALTIME, &timeElapse);//modificado
//Calcula la diferencia de tiempo
*timeInterval = timeDifference(&timeElapse,&timeReference);
return 0;
}
////////////////////////////////////////////////////////////////
/////////

9 Prctica 2 PSETR - El tiempo. Diseo de un cronmetro



// Funcion elapse2millis: Devuelve el intervalo de tiempo
transcurrido en milisegundos
// Param1: (OUT) Intervalo de tiempo en estructura timespec
// Return: Codigo error de la operacion (0 no hay error)
////////////////////////////////////////////////////////////////
////////
int elapse2millis(double *dIntervalMs)
{
struct timespec timeElapse;
struct timespec timeInterval;
//***************
//******Marca el instante de referencia del cronometro con
clock_gettime utilizando timeElapse
clock_gettime(CLOCK_REALTIME, &timeElapse);//modificado
//Calcula la diferencia de tiempo
timeInterval = timeDifference(&timeElapse,&timeReference);
//****************
//*** Calcula el tiempo en milisegundos teniendo en cuenta
que la estructura timespec tiene dos campos tv_sec y tv_nsec
//*** puedes utilizar MILI_PER_SECOND y MILI_PER_NANO
*dIntervalMs = (double) timeInterval.tv_sec*(double)
MILI_PER_SECOND;//modificado
*dIntervalMs += (double) timeInterval.tv_nsec*(double)
MILI_PER_NANO;//modificado
return 0;
}
////////////////////////////////////////////////////////////////
/////////
// Funcion elapse2micros: Devuelve el intervalo de tiempo
transcurrido en microsegundos
// Param1: (OUT) Intervalo de tiempo en estructura timespec
// Return: Codigo error de la operacion (0 no hay error)
////////////////////////////////////////////////////////////////
////////
int elapse2micros(double *dInterval)
{
struct timespec timeElapse;
struct timespec timeInterval;
//***************
//******Marca el instante de referencia del cronometro con
clock_gettime utilizando timeElapse
clock_gettime(CLOCK_REALTIME, &timeElapse);//modificado
//Calcula la diferencia de tiempo
timeInterval = timeDifference(&timeElapse,&timeReference);
//****************
//*** Calcula el tiempo en milisegundos teniendo en cuenta
que la estructura timespec tiene dos campos tv_sec y tv_nsec
//*** puedes utilizar MICRO_PER_SECOND y MICRO_PER_NANO

10 Prctica 2 PSETR - El tiempo. Diseo de un cronmetro



*dInterval = (double) timeInterval.tv_sec*(double)
MICRO_PER_SECOND;//modificado
*dInterval += (double) timeInterval.tv_nsec*(double)
MICRO_PER_NANO;//modificado
return 0;
}
////////////////////////////////////////////////////////////////
/////////
// Funcion getMicros: Obtiene el numero de microsegundos a
partir de un
//
un tiempo expresado en timespec
// Param1: (IN) Tiempo en estructura timespec
// Return: Microsegundos asociados al intervalo de tiempo
////////////////////////////////////////////////////////////////
////////
double getMicros(struct timespec *t1)
{
double delta;
//****************
//*** Calcula el tiempo en milisegundos teniendo en cuenta
que la estructura timespec tiene dos campos tv_sec y tv_nsec
//*** puedes utilizar MICRO_PER_SECOND y MICRO_PER_NANO
delta = (double) t1->tv_sec*(double)
MICRO_PER_SECOND;//modificado
delta += (double) t1->tv_nsec*(double)
MICRO_PER_NANO;//modificado
return delta;
}
////////////////////////////////////////////////////////////////
/////////
// Funcion getMillis: Obtiene el numero de millisegundos a
partir de un
//
un tiempo expresado en timespec
// Param1: (IN) Tiempo en estructura timespec
// Return: Millisegundos asociados al intervalo de tiempo
////////////////////////////////////////////////////////////////
////////
double getMillis(struct timespec *t1)
{
double delta;
//****************
//*** Calcula el tiempo en milisegundos teniendo en cuenta
que la estructura timespec tiene dos campos tv_sec y tv_nsec
//*** puedes utilizar MILI_PER_SECOND y MILI_PER_NANO
delta = (double) t1->tv_sec*(double)
MILI_PER_SECOND;//modificado
delta += (double) t1->tv_nsec*(double)
MILI_PER_NANO;//modificado
return delta;
}

11 Prctica 2 PSETR - El tiempo. Diseo de un cronmetro



////////////////////////////////////////////////////////////////
/////////
// Funcion getSeconds: Obtiene el numero de segundos a partir de
un
//
un tiempo expresado en timespec
// Param1: (IN) Tiempo en estructura timespec
// Return: Segundos asociados al intervalo de tiempo
////////////////////////////////////////////////////////////////
////////
double getSeconds(struct timespec *t1)
{
double delta;
//****************
//*** Calcula el tiempo en milisegundos teniendo en cuenta
que la estructura timespec tiene dos campos tv_sec y tv_nsec
//*** puedes utilizar SECOND_PER_NANO
delta = (double) t1->tv_sec;//modificado
delta += (double) t1->tv_nsec*(double)
SECOND_PER_NANO;//modificado
return delta;
}
////////////////////////////////////////////////////////////////
/////////
// Funcion getTimeSpec: Obtiene un tiempo en timespec de otro
expresado en
//
segundos
// Param1: (IN) Tiempo en segundos
// Return: Segundos asociados al intervalo de tiempo
////////////////////////////////////////////////////////////////
////////
struct timespec getTimeSpec(double *sec)
{
struct timespec tres;
double aux=*sec;
//****************
//*** Calcula el tiempo en timespec a partir de un tiempo
expresado en segundos. Recuerda que
//*** timespec tiene dos campos. Puedes utilizar
NANO_PER_SECOND
tres.tv_sec =(int)aux;
tres.tv_nsec =(aux-tres.tv_sec)*NANO_PER_SECOND;
return tres;
}

////////////////////////////////////////////////////////////////
/////////
// Funcion timeDifference: Obtiene la diferencia entre dos
instantes de
//
tiempo expresado en timespec t1 - t1
// Param1: (IN) Instante de tiempo t1

12 Prctica 2 PSETR - El tiempo. Diseo de un cronmetro



// Param2: (IN) Instante de tiempo t2
// Return: Estructura timespec diferencia
////////////////////////////////////////////////////////////////
////////
struct timespec timeDifference(struct timespec *t1, struct
timespec *t2)
{
struct timespec tres;
tres.tv_sec = t1->tv_sec - t2->tv_sec;
tres.tv_nsec = t1->tv_nsec - t2->tv_nsec;
if (tres.tv_nsec<0){
tres.tv_nsec=NANO_PER_SECOND + t1->tv_nsec - t2>tv_nsec;
tres.tv_sec--;
}
return tres;
}
////////////////////////////////////////////////////////////////
/////////
// Funcion timeSum: Obtiene la suma entre dos instantes de
//
tiempo expresado en timespec t1 + t1
// Param1: (IN) Instante de tiempo t1
// Param2: (IN) Instante de tiempo t2
// Return: Estructura timespec suma
////////////////////////////////////////////////////////////////
////////
struct timespec timeSum(struct timespec *t1, struct timespec
*t2)
{
struct timespec tres;
tres.tv_sec = t1->tv_sec + t2->tv_sec;
tres.tv_nsec = t1->tv_nsec + t2->tv_nsec;
if (tres.tv_nsec>=NANO_PER_SECOND){
tres.tv_nsec -= NANO_PER_SECOND;
tres.tv_sec++;
}
return tres;
}

medidatiempo2.c
/***************************************************************
****************
*
*
Practica #1: Tiempo. Mide el tiempo de la ejecucion de una
seccion de codigo
*
*
Autor: J.A. Holgado
*
Ultima modificacion: 29/03/15
*
Plataforma: POSIX
*
Asignatura: Desarrollo de Sistemas de Tiempo Real
*
Departamento: Lenguaje y Sistemas Informatico

13 Prctica 2 PSETR - El tiempo. Diseo de un cronmetro



*
Universidad de Granada
*
*
Objetivo: El objetivo de esta practica es medir el tiempo
en ejecutar una seccion de
*
codigo utilizando llamadas POSIX clock_gettime
*
****************************************************************
***************/
#include <time.h>
#include <stdio.h>
#include <crono.h>

//clock_gettime()
// printf()

//Inicio del programa principal


int main(int argc,char *argv[])
{
//Almacena la resolucion del reloj
struct timespec clock_res;
//Define variables
double total;
struct timespec timeInterval;
//Obtiene la resolucion del reloj del sistema por defecto
if ( clock_getres(CLOCK_REALTIME, &clock_res) == -1 ) {
perror( "clock get resolution" );
return -1;
}
//Mide el tiempo de una seccion de codigo
start(); //marcamos tiempo inicial
// Codigo a ejecutar------system(argv[1]);
elapse2timespec(&timeInterval);

//Se muestran los resultados


printf( "\nResultados de la llamada al sistema
clock_gettime():)\n\n");
printf( "Resolucion del reloj: %d segundos y %ld
nanosegundos\n",clock_res.tv_sec,clock_res.tv_nsec);
printf( "Tiempo total segundos: %.6f (s)\n",
getSecond(&timeInterval));
printf("Tiempo total en milisegundos: %.6f (ms)\n",
getMillis(&timeInterval);

14 Prctica 2 PSETR - El tiempo. Diseo de un cronmetro



printf("Tiempo total en microsegundos: %.6f (us)\n",
getMicro(&timeInterval);
}

You might also like