P2_PSETR

14
PROGRAMACIÓN DE SISTEMAS EMPOTRADOS Y DE TIEMPO REAL Práctica 2 El tiempo. Diseño de un cronómetro Mario Piñero de Mier Tomás Ruz Rodríguez Eduardo Bailón Martínez

description

sistemas en tiempo real

Transcript of P2_PSETR

  • 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)

    Tiempo promedio (1 iteracin) (s) Tiempo total (s)

    QNX 999847 927.858016 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:

    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 //clock_gettime()

    0

    500000

    1000000

    1500000

    2000000

    2500000

    3000000

    3500000

    4000000

    4500000

    5000000

    Baja Media Alta Tiem

    po de ejecuc

    in (nan

    oseg

    undo

    s)

    QNX

    Linux

  • 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 1e-3 #define MILI_PER_NANO 1e-6 #define SECOND_PER_NANO 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_nsectv_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 //clock_gettime() #include // printf() #include //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); }