J. Ułasiewicz Komputerowe systemy sterowania 1
Timery
1. Informacje podstawowe
Timer – mechanizm pozwalający na precyzyjne odmierzanie czasu i generowanie zdarzeń:
1. Sygnałów
2. Depozytów
Timer może być użyty do:
1. Precyzyjnego odmierzania odcinków czasu 2. Odblokowaniu procesu w ściśle określonym momencie czasu 3. Zabezpieczenia operacji blokujących.
Dalej będzie przedstawiona implementacja timerów według POSIX i UNIX (Open Group Specification)
Podstawowe funkcje dotyczące timerów: timer_create Tworzenie
timera
timer_settime Ustawienie
timera
timer_gettime
Testowanie stanu timera
timer_delete Kasowanie
timera
sygnal
proxy
TIMER
blokada
Timer odblokowuje zablokowany proces 2. Funkcje obsługi timera
2.1. Tworzenie
timera
Przed użyciem timer powinien być utworzony. Tworzenie timera następuje poprzez wykonanie funkcji timer_create.
#include <time.h>
#include <signal.h>
timer_t timer_create(clockid_t clockid, struct sigevent * evp); Instytut Cybernetyki Technicznej Politechniki Wrocławskiej
J. Ułasiewicz Komputerowe systemy sterowania 2
Gdzie:
Clockid identyfikator
źródła czasu (CLOCK_REALTIME)
evp
struktura ze specyfikacją typu zdarzenia Gdzie:
sigevent.sigev_signo > 0
Specyfikacja numeru sygnału
sigevent.sigev_signo < 0
Specyfikacja numeru depozytu (proxy) Funkcja zwraca:
> 0 Identyfikator timera
- 1 Błąd
Działanie funkcji polega na utworzeniu timera. Przy tworzeniu określa się czy timer ma generować sygnał czy depozyt. Nowo utworzony timer jest zablokowany. Trzeba go jeszcze ustawić przy pomocy funkcji timer_settime.
Przykłady:
a) sigevent.sigev_signo = SIGALRM
b) proxy = qnx_proxy_attach(0,0,0,-1) sigevent.sigev_signo = - proxy;
2.2. Ustawienie
timera
Ustawienie timera polega na określeniu:
-
Trybu odmierzania czasu
-
Czasu wyzwolenia
-
Okresu repetycji
int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue);
Gdzie:
timerid Identyfikator
timera
flags
Flagi (TIMER_ABSTIMER, TIMER_ADDREL) value
Nowa specyfikacja czasu generacji zdarzenia ovalue
Stara specyfikacja czasu generacji zdarzenia Zamiast ovalue można użyć NULL.
struct itimerspec {
struct timespec it_value;
// pierwsze odpalenie
struct timespec it_interval;
// interwał
int notify_type;
// sygnał lub proxy
int timer_type;
// absolutny lub relatywny
}
Instytut Cybernetyki Technicznej Politechniki Wrocławskiej
J. Ułasiewicz Komputerowe systemy sterowania 3
struct timespec {
long tv_sec; // sekundy
long tv_nsec; // nanosekundy
}
Czas pierwszego
tv_sec
it_value
odpalenia
tv_nsec
Interwal
it_interval
tv_sec
notify_type
timer_type
tv_nsec
struct itimerspec
struct timespec
Czas T
Postać struktury itimerspec
Gdy it_interval = 0
to brak repetycji
Gdy it_value = 0
to timer zabroniony
Funkcja zwraca:
o
Sukces
-1
Błąd
Gdy bit flag TIMER_ABSTIMER jest ustawiony timer będzie wyzwolony gdy czas bieżący zrówna się z czasem wyspecyfikowanym w polu it_value.
Gdy bit flag TIMER_ADDREL jest ustawiony czas będzie liczony od chwili bieżącej (czas relatywny).
2.3. Testowanie czasu do wyzwolenia timera
Do testowania czasu jaki pozostał do wyzwolenia timera używa się funkcji timer_gettime.
int timer_gettime(timer_t timerid, struct itimerspec *value); Gdzie:
timerid Identyfikator
timera
value
Nowa specyfikacja czasu generacji zdarzenia Funkcja zwraca:
o
Sukces
-1
Błąd
Instytut Cybernetyki Technicznej Politechniki Wrocławskiej
J. Ułasiewicz Komputerowe systemy sterowania 4
2.4. Kasowanie
timera
Timer kasuje się za pomocą funkcji: int timer_delete(timer_t timerid) Gdzie:
timerid Identyfikator
timera
Funkcja zwraca:
o
Sukces
-1
Błąd
Instytut Cybernetyki Technicznej Politechniki Wrocławskiej
J. Ułasiewicz Komputerowe systemy sterowania 5
3. Przykład zastosowania timera W poniższym przykładzie timer generuje pierwszy depozyt po upływie 4 sekund.
Następne generuje co 1 sekundę.
// Demonstracja dzialania timera
// (C) J. Ulasiewicz 2005
#include <stdio.h>
#include <time.h>
#include <sys/kernel.h>
#include <sys/timers.h>
struct {
int
type;
// typ
char text[64]; // pole tekstu
} msg;
main()
{ int res,i = 0;
timer_t id;
pid_t proxy;
struct itimerspec timer;
struct sigevent
event;
/* Utworzenie proxy --------------------*/
proxy = qnx_proxy_attach(0,0,0,-1);
/* Utworzenie timera --------------------*/
event.sigev_signo = -proxy;
id = timer_create(CLOCK_REALTIME,&event);
/* Ustawienie timera --------------------*/
timer.it_value.tv_sec
= 4L;
timer.it_value.tv_nsec
= 0L;
timer.it_interval.tv_sec
= 1L;
timer.it_interval.tv_nsec = 0L; timer_settime(id,0,&timer,NULL); while(1) {
Receive(proxy,&msg,sizeof(msg)); printf("Wyzwolenie: %d\n",i++);
};
/* Skasowanie timera ------*/
timer_delete(id);
exit(0);
}
Przykład zastosowania timera do cyklicznej generacji depozytu Instytut Cybernetyki Technicznej Politechniki Wrocławskiej