|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Member
Iscritto dal: Sep 2001
Messaggi: 181
|
Linux: garantire periodicità in c
Consigli? immag un thread che mi faccia da contatore di tick, e per ogni tick controlla quale periodo è scaduto, come posso implementarlo?considerate anche il fatto che l'applicativo si resetterà/ammazzerà una volta ogni 10 anni...insomma deve stare sempre su, quindi un minimo ritardo.....
Si potrebbe pensare anche di gestire un fattore di correz, ma...se il ritardo fosse deterministico...insomma nn ci riesco proprio!! Qualcuno è in grado di aiutarmi? avevo provato con la setitimer catturando il sigalarm ma...dopo un po', nn ricordo con precisione, inizia a inviare sigalarm in modo del tutto irregolare...ovviamente la priorità del thread e del processo è massima!!! con la select...cmq ho avuto dei problemi. Poi ho iniziato a pensare di catturare degli IRQ o leggere RTC....cosa ne pensate? qualcuno ha mai implementato qualcosa interfacciandosi con il RealTimeClock? (ovviamente sto parlando di quello HW). HELP!! avevo provato con la setitimer catturando il sigalarm ma...dopo un po', nn ricordo con precisione, a inviare sigalarm in modo del tutto irregolare...ovviamente la priorità del thread e del processo è massima!!! con la select...cmq ho avuto dei problemi. |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Puoi essere più preciso su quello che ti serve e sulle latenze temporali massime che puoi tollerare?
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
|
|
|
|
#3 |
|
Member
Iscritto dal: Sep 2001
Messaggi: 181
|
semplifichiamo il tutto...immagina un timer manager che scandisce i tick e dei oggettini timeout che si iscrivono fornendogli un periodo(il periodo min e' di 250ms)...il timer manager allo scadere di ogni tick controlla se è scaduto qualche periodo, nel caso positivo invoca il metodo treat_event del obj timeout.
circa l'errore accettabile...è tutto relativo, se avessi un errore fisso in percentuale...mi andrebbe ancora bene;inserirei un fattore di correz ma.....se l'errore è variabile.....è la fine!! La cosa importante è che ogni oggetto time out e' preciso nell'effettuare l'azione prestabilita!! Se il TimerManager porta un ritardo con il trascorrere del tempo nn avro + che un determinato obj timeout che ripete la sua azione periodicamente.... mi spiego meglio con un es. supponi di dover supervisionare il funzionmento di un partiolare sottosistema, esso invia dei msg di keep elive(via socket, seriale o....) periodicamente se...dovesse scattare un periodo max il sottosistema si ritiene fuori uso....ogni volta che si riceve tale info il timer si resetta;quindi un ritardo/anticipo nn controllato...va be hai capito. Ovviament il prob è semplificato ma....rende bene l'idea! |
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Più o meno. Non mi è ancora chiaro se puoi tollerare errori sistematici. Ad esempio è un problema se invece dei tuoi 250ms ti ritrovi con dei timeout variabili tra 255 e 265? Trattandosi (se non ho capito male) di un "timeout", non dovrebbe essere un fattore critico.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
|
|
|
|
#5 |
|
Member
Iscritto dal: Sep 2001
Messaggi: 181
|
Perchè mi fai questa domanda hai una soluzione? postala...magari assieme possiamo trovare una soluzione, ammettendo che esista su questa piattaforma...
Il discorso è che stiamo parlando di un errore percentuale che varia tra il 2,5% e il 7,5% a prescindere del periodo? Quindi su un timer di 1h perderei al max 4,5 sec...non è proprio la precisione che richiedevo, su timer di questo periodo posso perdere al max 2 sec. Mi va bene un errore ma....che sia fisso in percentuale o...quantomeno che dipenda da quache cosa; se pur riesco ad implementare il tutto con un alto errore ma che riesco a determinarlo...va benissimo, lo si gestisce in qualche modo! |
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Il problema è concettuale, non implementativo.
Da quello che ho capito, ti serve un timeout per verificare che non cessi una certa attività. Se è così, non devi curarti del timeout effettivo, purché sia _superiore_ a un _minimo_ che stabilisci: la precisione, in questo caso, non ha grande importanza. Inoltre, il periodo di timeout dovrebbe essere resettato ogni volta che rilevi un evento che stai monitorando (ad es. come accade con i watchdog hardware). Normalmente si fa così. Per questo ti sto facendo tutte queste domande: se ti serve un timeout, non importa la precisione. Altrimenti dovresti spiegarmi meglio le tue necessità e perché hai bisogno di precisione, in quanto ci sono n modi che potrei consigliarti per fare timer più o meno precisi (e ovviamente più o meno complicati) -- ma non sono utilizzati per dei semplici rilevatori di timeout.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
|
|
|
|
#7 |
|
Member
Iscritto dal: Sep 2001
Messaggi: 181
|
Quello che mi serve è un timer, per svariati usi, con la max precisione ma che si puo' avere.
ti faccio un es degli n utilizzi che dovrei farne: supponi che esistano due sottosistemi (vediamoli come due processi) che inviano msg ogni 100ms per avvertire che stanno funzionando(insomma che stanno su), immagina che questi sottosistemi prendono informazioni da msg(miei) per agire su dispositivi HW...il mio processo deve accorgersi entro un max di 250ms(parametro configurabile da file da leggere allo start-up.. dipende dal HW) che un sottosistema nn funziona e dare gli input all'altro in modo del tutto differente(interfac diverse), considera inoltre che il sottosistema nn accetta + gli input se scadono quei famosi 250ms(in effetti sono 250+50 dove il 250 e' sempre configurabile) e tutto il sistema(tutti i processi) cade!! In questo caso esisterà un timeout che si scrive al TimerManager con un periodo di 250ms, scaduto il quale=>Non ricezione Msg E' ovvio che ogni qual volta mi arriva un msg io resetto il timeout ma...nn ho capito come nn puo' interessare la precisione. Ecco come un ritardo potrebbe causare "un disastro".... Ultima modifica di cavay : 29-09-2004 alle 19:40. |
|
|
|
|
|
#8 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Ok quindi ti serve un timeout massimo perché devi poter gestire l'evento in via alternativa in tempo utile.
250ms sono un bel periodo, devi considerare però la differenza tra il timeout minimo e quello massimo. Se ad es. il minimo è 100ms e il massimo è 250, hai un ottimo margine. Inoltre hai un piccolo problema di lock: se ti scade il timeout e decidi di processare per via alternativa, il processamento "normale" deve essere annullato. La famiglia di funzioni che possono aiutarti nel compito sono le pthread_cond_*, che fortunatamente sono associate a un mutex che ti consente di evitare facilmente fastidiose race. Ne è stato parlato qualche giorno fa di queste funzioni, puoi cercare il thread tra quelli passati. In sintesi quello che deve fare il tread di monitoraggio è un pthread_cond_timedwait, attendendo un evento per un periodo di timeout che stabilisci. Chi deve effettuare l'operazione, prima blocca il mutex associato alla condizione, gestisce l'evento, e "sveglia" il thread tramite pthread_cond_signal in modo da segnalare l'avvenuta corretta operazione. Se ciò non avviene entro l'istante specificato, la pthread_cond_timedwait ritornerà con un errore (ETIMEDOUT). Il resto sono dettagli implementativi (sincronizzazione, eventuale aumento della priorità nel thread di monitoraggio ecc.) Mi sembra la strada più appropriata al tuo problema. Il resto è fare pratica con queste funzioni, che in un primo momento possono non essere intuitive per come gestiscono il mutex associato.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 Ultima modifica di ilsensine : 29-09-2004 alle 20:15. |
|
|
|
|
|
#9 |
|
Member
Iscritto dal: Sep 2001
Messaggi: 181
|
Conosco le primitive, la settimana prox provo a tirar su uno schizzetto di programma e ti farò sapere..
Grazie per la collaborazione |
|
|
|
|
|
#10 |
|
Member
Iscritto dal: Sep 2001
Messaggi: 181
|
ops...anche questa primitiva non va bene, porta ritardi.
Quello che ho fatto è eliminare il timer manager e implementare un timer singolo: il work del tread riassunto: gettimeofday Tempo1 pthread_cond_timedwait aspetto il time out impostato gettimeofday Tempo2 cout Tempo2-Tempo1 Impostando un periodo di un secondo mi porta un ritardo VARIABILE, ritardo medio poco meno di 20ms(ovviamente il tread timer è stato integrato nell'applicazione con priorità max e il proc lanciato con nice -20). Quindi anche questo tentativo sembra nn essere buono... E' possibile che nessuno mai abbia implementato un timer su linux-intel? Quello che mi servirebbe è un semplice timer con tre metodi Start(periodo) TimeOutElapsed() Stop() ma con alta precisione su kernel 2.4....veramente nn è possibile! Ultima modifica di cavay : 04-10-2004 alle 15:06. |
|
|
|
|
|
#11 | ||
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
Stai usando un kernel 2.6? Quote:
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
||
|
|
|
|
|
#12 |
|
Member
Iscritto dal: Sep 2001
Messaggi: 181
|
scusa ma...avevo commesso un errore, il ritardo era di 20 ms e nn 2.
Il kernel della macchina target è il 2.4 |
|
|
|
|
|
#13 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
Il semplice passaggio al kernel 2.6 ti migliora le latenze di un ordine di grandezza. Scendere sotto il ms è più complicato.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
|
|
|
|
|
#14 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
|
|
|
|
|
|
#15 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
Per latenze nell'ordine del paio di ms il kernel 2.6 va bene. In casi particolari anche per latenze inferiori.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
|
|
|
|
|
|
#16 |
|
Member
Iscritto dal: Sep 2001
Messaggi: 181
|
Quindi su questa piattaforma la soluzione nn esiste?
Cmq....ho provato, per sfizio, sul kernel 2.6 ma....i risultati nn sono stati ecellenti; è vero che si migliora e pure di tanto ma...nn come dovrebbe! Non so cosa siano le RTAI, mi informo un po e ...se posso e se servono le utilizzo; cmq la piattaforma è sempre linux intel kernel 2.4 |
|
|
|
|
|
#17 | ||
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Quote:
Quote:
Puoi usare l'rtc, ma sei vincolato a tick in istanti precisi nel tempo (cioè non puoi dire "resetta il timer su questo istante" -- non che io sappia). Con l'rtc puoi ottenere accuratezze nell'ordine di (1+-0.1) us (sul kernel 2.6 e scheduler SCHED_FIFO). Se vuoi ti posto un codice di esempio.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 |
||
|
|
|
|
|
#18 |
|
Member
Iscritto dal: Sep 2001
Messaggi: 181
|
te ne sarei veramente grato
|
|
|
|
|
|
#19 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
|
Questo programma imposta un intervallo del timer (settato dalla macro DELTA -- deve essere <= 8192), e calcola la media e dev. standard di quanto si discosta dall'istante temporale atteso. Se lo esegui con i privilegi di root sul kernel 2.6, otterrai i risultati che ho citato. Anche con il kernel 2.4 puoi ottenere buone prestazioni:
Codice:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/poll.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <linux/rtc.h>
#include <math.h>
#include <sched.h>
#include <string.h>
static unsigned int __us(void) {
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_usec+tv.tv_sec*1000000;
}
static void __attribute__((__noreturn__)) fail(const char *fnc) {
perror(fnc);
exit(-1);
}
#define RATE 64
#define DELTAS 1024
int main(void) {
int fd;
double sum = 0.0;
double var = 0.0;
double delta;
double deltas[DELTAS] = { 0.0, };
int dpos = 0;
const double r = 1000000.0/RATE;
unsigned int items = 0;
struct pollfd pfd;
unsigned int t1;
unsigned int t2;
int rep;
struct sched_param p;
p.sched_priority = 10;
if(sched_setscheduler(getpid(), SCHED_FIFO, &p))
perror("sched_setscheduler");
if(mlockall(MCL_CURRENT|MCL_FUTURE))
perror("mlockall");
fd = open("/dev/rtc", O_RDONLY);
if(fd<0) fail("open");
if(ioctl(fd, RTC_IRQP_SET, RATE)<0)
fail("ioctl(RTC_IRQP_SET)");
pfd.fd = fd;
pfd.events = POLLIN;
for(rep=0; rep<10; ++rep) {
ioctl(fd, RTC_PIE_ON);
poll(&pfd, 1, -1);
ioctl(fd, RTC_PIE_OFF);
}
t2 = __us();
while(1) {
t1 = t2;
ioctl(fd, RTC_PIE_ON);
poll(&pfd, 1, -1);
t2 = __us();
ioctl(fd, RTC_PIE_OFF);
delta = fabs(r-(double)(t2-t1));
sum += delta - deltas[dpos];
var += delta*delta - deltas[dpos]*deltas[dpos];
deltas[dpos] = delta;
items<DELTAS && ++items;
++dpos>=DELTAS && (dpos = 0);
!--rep && (
fprintf(stderr, "avg=%0.2f us stddev=%0.3f us\n",
sum/items, items>1 ? sqrt(var)/(items-1) : sqrt(-1.0)),
(rep = 10)
);
}
}
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12 Ultima modifica di ilsensine : 04-10-2004 alle 17:23. |
|
|
|
|
|
#20 |
|
Member
Iscritto dal: Sep 2001
Messaggi: 181
|
Grazie, ho tratto un po' di cose e implementato il TimerMenager....sembra che funzioni piuttosto bene. Devo fare ancora delle misure + serie ma...sono ottimista.
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 17:40.



















