Sunteți pe pagina 1din 3

Programarea aplicatiilor in timp-real Laborator 11

Planificarea taskurilor pe conditie de timp. Contoare de timp (timer-e)


Accesul la o baza de timp se poate realiza sub QNX cu functii standard (tabelul 1) sau cu functii care urmeaza standardul POSIX (tabelul 2). Avand acces la o baza de timp, pot fi definite trei tipuri de operatii realizate in functie de timp: asteptare un interval de timp T (de exemplu, sleep, pause, etc); operatii periodice cu perioada de timp specificata, T; executie a unei operatii unice la un moment specificat de timp absolut (de exemplu, la HH:MM:SS) sau relativ (de exemplu, peste T). Standardul ANSI C furnizeaza o biblioteca standard pentru interfatarea cu timpul "calendaristic". Aceasta defineste timpul sub forma time_t (in secunde) si mai multe rutine pentru manipularea obiectelor de tip timp (tabelul 1).

Programarea aplicatiilor in timp real. Teorie si practica, capitolul 6, pag 169

a) citirea timpului calendaristic QNX (ca si celelalte sisteme UNIX tipice) memoreaza data si timpul ca o unica valoare (numarul de secunde de la 1 ianuarie 1970, ora 00:00:00 ) intr-o variabila time_t:
#include <time.h> time_t now; char *ptr; struct tm *tod; time(&now); tod = localtime(&now); // converteste la un sir de caractere printf("Este ora %s\n", ptr);

b) calculul duratei unui eveniment Deoarece functia time() calculeaza timpul in secunde, poate fi folosita pentru calculul intervalelor de timp pentru diferite sectiuni ale unui program, presupunand ca o rezolutie de o secunda este suficienta.
time_t start, interval; start = time(NULL); . .// executie sectiune de cod . interval = time(NULL) - start;

In plus, se poate folosi functia difftime(), care returneaza o valoare de tip double:
diff = difftime(time(NULL), start);

In plus, standardul POSIX furnizeaza in implementare mai multe "ceasuri" (tabelul 2). Fiecare ceas are propriul sau identificator (de tipul clockid_t), standardul IEEE impunand si existenta unui ceas de timp-real (CLOCK_REALTIME). Standardul POSIX impune ca rezolutia minima a ceasului de timp-real CLOCK_REALTIME sa fie de 50 Hz (20 ms).
1

Valoarea returnata de un "ceas" (prin intermediul functiei clock_gettime()) este data de o structura timespc (vezi tabelul 2). tv_sec reprezinta numarul de secunde care au trecut de la 1 ianuarie 1970, iar tv_nsec reprezinta o valoare aditionala in nanosecunde. Functia clock_getres() permite determinarea rezolutiei ceasului.

Programarea aplicatiilor in timp real. Teorie si practica, capitolul 6, pag 169, Interfata C / POSIX pentru accesul la ceas

c) operatii de delay Procesele trebuie sa aiba posibilitatea de a-si intarzia (engl. delay) executia fie pe o perioada relativa de timp, fie pana la un anumit moment in viitor. Sub standardul POSIX, un delay poate fi obtinut prin intermediul apelurilor de sistem sleep (pentru rezolutii mari, de exemplu un delay de ordinul secundelor) sau nanosleep (pentru rezolutii mai mici). Ultimul apel este masurat in functie de ceasul de timp-real CLOCK_REALTIME. Un proces se poate auto-suspenda pe un interval de maxim 65535 secunde apeland functia sleep():
sleep(10); // sleep de 10 secunde

Sistemul de operare in timp-real QNX asigura si delay-uri de ordinul milisecundelor:


delay(250); // suspenda procesul pentru 250 ms

Pentru intervale foarte mici de timp se poate folosi functia nanosleep():


#include <time.h> struct timespec interval, remaining; interval.tv_spec = 0; // 0 secunde interval.tv_nsec = 100; // 100 nanosecunde nanosleep(&interval, &remaining);

Timere Un timer este asemanator unui ceas cu alarma care face o numaratoare inversa pe un anumit interval, semnalizand expirarea acestuia. Spre deosebire de sleep, un timer nu suspenda procesul apelant. Cea mai generala modalitate de setare a unei baze de timp prin intermediul timer-elor o ofera functia timer_settime(), tabelul 3.

Programarea aplicatiilor in timp real. Teorie si practica, capitolul 6, pag 169, Functii QNX pentru timere Formatul de apel al unui timer este urmatorul:
#include <time.h> #include <signal.h> // este nevoie de un identificator de timer, de o specificatie // de timer si una de eveniment timer_t tid; struct itimerspec timer; struct sigevent event; // seteaza "signal number" la 0, ceea ce inseamna sleep

event.sigev_signo = 0; // creeza un timer; primul parametru e intotdeauna // CLOCK_REALTIME, iar al doilea specifica tipul evenimentului timer_create(CLOCK_REALTIME, &event, &tid); // seteaza parametrul timer-ului la 10 secunde, 0 nanosecunde timer.it_value.tv_sec = 10L; timer.it_value.tv_nsec = 0L; // seteaza parametrii pentru repetarea automata a timer-ului timer.it_interval.tv_sec = 0L; timer.it_interval.tv_nsec = 0L; // porneste timer-ul, adica intra in sleep pentru 10 secunde timer_settime(tid, 0, &timer, NULL);

Desfasurarea lucrarii: Exemplul 1. Accesul la o baza de timp cu functii standard. Programul CitireTimp.c Exemplul 2. Executie periodica cu ajutorul timerelor. Exemplu de initializare a unui timer, care la expirare, trimite un puls. Primul interval de asteptare este de 1.5 secunde, intervalul de repetare este fiecare la 1.5 secunde notificare cu ajutorul pulsurilor Pulsuri.c Tema: 1. Sa se implementeze o aplicatie formata din mai multe taskuri, in care se vor executa actiuni periodice. Actiunile periodice din cadrul taskurilor vor fi pornite conform schemei de planificare cu task planificator. Incercati sa definiti si sa porniti mai multe timere intr-o aplicatie. Folositi semafoare sau alte mecanisme de sincronizare pentru a sincroniza taskurile. 2. Cum puteti masura timpul necesar pentru a executa secvente de actiuni in taskuri?