Come posso fare in modo dinamico il trasferimento dei dati e la gestione della memoria attraverso i thread in C?

StackOverflow https://stackoverflow.com/questions/689514

  •  22-08-2019
  •  | 
  •  

Domanda

Piattaforma:ARM9

Linguaggio Di Programmazione C

Requisiti di pianura C e verso l'esterno libs e non spinta.

OS - REX RTOS

Ho due thread in esecuzione in una piattaforma embedded -

  1. uno è a livello di driver per gestire tutta la comunicazione e il trasferimento dei dati con l'hardware.
  2. il secondo thread esegue l'applicazione che utilizza i dati da/per l'hardware.

L'idea è di separare l'app thread dal driver thread in modo che possiamo cambiare l'hardware e realizzazione di driver hardware thread, ma hanno un impatto minimo sul thread dell'applicazione.

Il mio problema è che i dati ricevuti dall'hardware può essere dinamico, ovveronon sappiamo in anticipo la quantità di memoria che il thread dell'applicazione devono mettere da parte per ogni richiesta da/per l'hardware in quanto questo è determinato a run-time.

Stavo pensando che il driver thread potrebbe informare il thread dell'applicazione che c'è tanto di dati da leggere.Il thread dell'applicazione alloca la memoria e le richieste del driver thread per leggere i dati.È poi il thread dell'applicazione per elaborare i dati di conseguenza.In questo modo, tutta la gestione della memoria è all'interno del thread dell'applicazione.

È stato utile?

Soluzione

Paio di opzioni che vengono in mente:

1) malloc la memoria del driver, la connessione con il programma.Ma...si tende a evitare di usare malloc in qualcosa che si avvicina ad un vero e proprio requisito di tempo.Se si dispone di accesso a malloc/free, e non ci sono "in tempo reale", le preoccupazioni o problemi di frammentazione della memoria (es.il mucchio è abbastanza grande), quindi questo è un abbastanza facile approccio.Il driver invia il puntatore allocato per l'applicazione del filo tramite una coda di messaggi e app gratis la memoria quando fatto.Guardare fuori per le perdite di memoria.

2) Anello circolare o buffer.Il driver gestisce completamente una dimensione fissa ring buffer e semplicemente manda un messaggio per l'applicazione quando un buffer è pronto.Vedi qui per alcuni dettagli: Buffer circolare.Quindi l'applicazione di marchi di dati "disponibile", sempre con un driver API, che consente di nascondere l'anello buffer dettagli dell'app thread.Possiamo utilizzare questo approccio per uno dei nostri autisti, che è molto simile serie di requisiti come tu descrivi.In questo caso, è necessario essere interessati con la determinazione del "migliore" dimensioni di buffer circolare di gestire l'overflow nel driver, etc.

buona fortuna!

Altri suggerimenti

Non si specifica un OS, ma in qualche modo hanno "thread".Salvo che uno di loro sia a livello di driver (interrupt handler) e l'altro suona come un'applicazione (userland/kernel).Ma che non corrisponde, perché il driver e app in grado di comunicare prima che i dati vengano trattati.

La terminologia è fonte di confusione e non sono incoraggianti.È questo un homebrew (RT)OS o no?

Se si dispone di un vero e proprio OS, sono istituiti i metodi per la scrittura di driver e trasmissione dati per userland.Leggere la documentazione o utilizzare uno dei driver esistenti come riferimento.

Se questo è un sistema operativo personalizzato, si può ancora fare riferimento ad altri driver open source per le idee, ma chiaramente non hanno impostato le cose in modo agevole.Preallocare la memoria il codice del driver, da riempire con i dati, come si arriva, e la mano al codice dell'applicazione.La quantità di memoria sarà una funzione della velocità di app in grado di elaborare dati, la più grande quantità di dati che si intende accettare, e quanto i dati interni di accodamento è necessaria per supportare la vostra applicazione.

Questo è 'C', ho finito per rendere l'app registrare un callback con il driver.Lo scopo della funzione di callback è quello di elaborare i dati dopo che il driver lo legge dal dispositivo.Il driver gestisce la memoria, cioèalloca la memoria, richiama la richiamata e, infine, libera la memoria.Inoltre, la richiamata ha solo permesso di lettura sulla memoria.Pertanto, l'app dovrebbe idealmente basta copiare e incollare il contenuto del buffer di memoria e di uscita dalla richiamata subito.Poi si è liberi di elaborare i dati come e quando vuole.

Ho aggiornato la documentazione di rendere chiaro agli usi l'app di callback che si presume quando la richiamata restituisce la memoria non deve più essere considerato valido.Se il callback viene utilizzato in qualsiasi altro modo, il comportamento è indefinito.

Il mio primo pensiero sarebbe quello di utilizzare buffer circolare.Qui è un esempio di codice.Sentitevi liberi di adattare questo per propri usi.Voi probabilmente non si desidera che le variabili globali.E si potrebbe non voler #definisce:

#define LENGTH (1024)
#define MASK (LENGTH-1)
uint8 circularBuffer[ LENGTH ];
int circularBuffer_add = 0;
int circularBuffer_rmv = 0;

void copyIn( uint8 * circularBuffer, uint8 * inputBuffer, int n ) {
    int i;
    for( i = 0; i < n; i++ ) {
        circularBuffer[ circularBuffer_add ] = inputBuffer[ i ];
        circularBuffer_add = ( circularBuffer_add + 1 ) & MASK;
    } 
}

void copyOut( uint8 * circularBuffer, uint8 * outputBuffer, int n ) {
    int i;
    for( i = 0; i < n; i++ ) {
        outputBuffer[ i ] = circularBuffer[ circularBuffer_rmv ];
        circularBuffer_rmv = ( circularBuffer_rmv + 1 ) & MASK;
    } 
}

Anche il codice di cui sopra presuppone che l'unità di dati tipo di dati "uint8".Si può cambiare, in modo che usi qualche altro tipo di dati.O si può anche fare generica e utilizzare memcpy() per copiare in circularBuffer.

La caratteristica principale di questo codice è come gestisce la aggiungi e rmv ptr.


Una volta che si ottiene le cose di lavoro con il codice di cui sopra. Suggerisco a un certo punto di commutazione da tutte le letture dall'hardware usare la piattaforma diretta di accesso alla memoria API.

È importante per passare alla diretta di accesso alla memoria, perché il codice di cui sopra utilizza un sacco di cicli relativi al DMA che utilizza quasi zero cicli.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top