2010-09-13 6 views
5

Ho un sistema di flusso di dati asincrono scritto in C++. Nell'architettura del flusso di dati, l'applicazione è un insieme di istanze del componente, che vengono inizializzate all'avvio, quindi si comunicano reciprocamente con messaggi predefiniti. Esiste un tipo di componente denominato Pulsar, che fornisce un "segnale di segnale di clock" ad altri componenti che si collegano ad uno di essi (ad es. Delay). Emette un messaggio (chiama l'API del dispatcher del flusso di dati) ogni X ms, dove X è il valore del parametro "frequenza", che è indicato in ms.Qual è il modo ufficiale per chiamare una funzione (C/C++) in ab. ogni 1/100 sec su Linux?

Breve, l'operazione è solo per chiamare una funzione (metodo) in ogni X ms. La domanda è: qual è il modo migliore/ufficiale per farlo? C'è qualche schema per questo?

ci sono alcuni metodi che ho trovato:

  • Usa SIGALRM. Penso che la segnalazione non sia adatta a questo scopo. Anche se la risoluzione è 1 secondo, è troppo raro.
  • Utilizzare l'interruzione HW. Non ho bisogno di questa precisione. Inoltre, sono a conoscenza dell'utilizzo di una soluzione correlata a HW (il server è compilato per diverse piattaforme, ad esempio ARM).
  • Misurare il tempo trascorso e dormire() fino alla prossima chiamata. Non sono sicuro che sia il modo migliore per misurare il tempo per chiamare le chiamate di sistema relative al tempo di 5 thread, ogni 10 volte al secondo - ma forse ho torto.
  • Utilizzare le funzioni del kernel RealTime. Non ne so nulla. Inoltre, non ho bisogno di una chiamata precisa di cristallo, non è un atomreactor e non posso installare il kernel RT su alcune piattaforme (anche il kernel 2.6.x è disponibile).

Forse, la risposta migliore è una breve parte commentata del codice sorgente di un lettore audio/video (che non riesco a trovare/comprendere da solo).

UPDATE (richiesto da @MSalters): il co-autore del progetto DF utilizza Mac OSX, quindi dovremmo trovare una soluzione che funzioni sulla maggior parte di Posix-compilant op. sistemi, non solo su Linux. Forse, in futuro ci sarà un dispositivo di destinazione che usa BSD, o qualche Linux limitato.

+3

Un segnale è appropriato nonostante le tue prenotazioni. Controlla 'man setitimer', provaci e facci sapere se hai problemi reali. Se stai già bloccando qualcosa come select(), puoi usare invece un valore di timeout. –

+0

Segnala una buona scelta per un'app multithread? Quando arriva un segnale, dovrebbe essere "inviato" al thread appropriato. – ern0

+0

Le maschere di segnale sono per-thread, quindi puoi bloccare 'SIGALRM' in ogni altro thread. – caf

risposta

2

Per essere onesti, penso che dover avere un "pulsar" in quello che afferma di essere un sistema di flusso di dati asincrono è un difetto di progettazione. O è asincrono o ha un evento di sincronizzazione dell'orologio.

Se si dispone di un componente che richiede un ritardo, richiedere uno, tramite boost::asio::deadline_timer.async_wait o una delle soluzioni di livello inferiore (select()/epoll()/timer_create()/etc). In entrambi i casi, la soluzione più efficace C++ è probabilmente i timer boost.asio, poiché utilizzerebbero la soluzione più efficiente sulla versione del kernel di Linux.

+0

Non uso Boost né altre librerie (solo: stdlib, pthreads). Possiamo aprire una discussione sul design; il mio obiettivo era mantenere il Dispatcher (a volte chiamato anche broker, scheduler) il più debole possibile, ecco perché Pulsar è un componente separato. Forse, un giorno Dispatcher fornirà funzioni/servizi timer, ma alimenterà Pulsar. Esistono già altre funzioni speciali di Dispatcher, accessibili tramite i componenti (uno ad esempio: l'ordine dei messaggi). Devo dire che il mio sistema è in stato "prototipo": funziona, ma c'è una cosa da fare. – ern0

+2

Bene, per quanto riguarda il design, andrei con timer_create()/timer_settime(). Non dimenticare di inserire SIGEV_THREAD in sigev_notify per timer_create, in modo che fornisca le scadenze del timer al thread, anziché elaborare. Non sarebbe un "++ modo ufficiale C", ma sarebbe "via ufficiale POSIX". – Cubbi

+0

Non sapevo che i segnali sono così filo-friendly, ci proverò. – ern0

3

Se non hai bisogno di dure garanzie in tempo reale, usleep dovrebbe fare il lavoro. Se si desiderano garanzie dure in tempo reale, sarà necessaria una funzione basata su interrupt o su kernel in tempo reale.

+2

usleep è obsoleta si dovrebbe utilizzare nanosleep o si seleziona – aeh

+0

nanosleep è fresco, racconta il tempo restante al momento dell'interruzione, ma ho bisogno di chiamare una funzione di tempo ancora letto ogni round per correggere la quantità di dormire, e io non voglio . – ern0

2

Un'alternativa agli approcci precedentemente menzionati consiste nell'utilizzare il supporto Timer FD in Linux Kernel 2.6.25+ (praticamente qualsiasi distribuzione vicina a "corrente"). Gli FD timer offrono una maggiore flessibilità rispetto agli approcci precedenti.

+0

Sì, è così bello! Ma io non voglio far cadere la compatibilità BSD (il mio amico, che è co-autore in questo progetto, sta utilizzando Mac, sfortunatamente). – ern0

+0

@ ern0: Si prega di aggiungere tali preoccupazioni per la domanda! – MSalters

1

Trascurare la questione del design (che credo sia una domanda interessante, ma merita proprio thread) ...

Vorrei iniziare con la progettazione di un'idea 'interruzione', e l'utilizzo di segnali o qualche funzione del kernel per interrompere ogni X usec. Ritardavo a fare funzioni di sonno finché le altre idee non erano troppo dolorose.

Problemi correlati