2016-02-01 16 views
5

Ho un codice di controllo in esecuzione robot con priorità in tempo reale su un sistema operativo Linux con patch PREEMPT-RT su un Beaglebone Black. Tutto il codice è scritto in C e funziona a 500Hz.Picchi di latenza durante l'acquisizione dei dati in Linux embedded in tempo reale

Ho notato una latenza nell'intervallo di poche centinaia di millisecondi ogni tanto durante l'esecuzione del codice e l'ho rintracciata nella funzione di registrazione dei dati che ho scritto. Questa latenza causa il fallimento del controllo del mio robot poiché dipende molto dalla funzionalità in tempo reale.

La parte di codice pertinente è riportata di seguito. Ho tagliato un sacco di codice per chiarezza, ma modifico questo post se è necessario qualcosa.

FILE *file; 

int main(int argc, char** argv) { 
    file = fopen(logname, "w"); 

    while (1) { 
     /* Control code stuff*/ 

     logData(); 

     time_msec = time_msec + controlLoopTime; 
    } 
} 

void logData() { 
    if (time_msec - logTimer_msec >= LOG_TIMER) { 
     logTimer_msec = time_msec; 

     if (!bLogCreated) { 
      fprintf(file, 
        "SensorData1 SensorData2 SensorDataN" 
        ); 
      bLogCreated = TRUE; 
     } 

     // log data to file 
     fprintf(file, 

       "%.2f %.2f\n", 

       sensorData1, sensorData2, sensorDataN 
     ); 
    } 
} 

Ho bisogno di registrare dati da più variabili (probabilmente 20-50) ad una buona frequenza, forse 100-125Hz. Non è necessario che i dati vengano registrati alla velocità di controllo (ogni 2 ms), ma l'ho ridotto a 12 ms e continuo a vedere picchi di latenza ogni pochi minuti.

La latenza può essere un problema con la chiamata fprintf. Si tratta di una limitazione del BeagleBone Black, del mio codice o solo della natura del data logging?

Una domanda simile è stato chiesto qui, ma non sembrava per affrontare il mio problema: Finding latency issues (stalls) in embedded Linux systems

+1

Un handle di file non tty è un buffer di blocco predefinito. Quindi dopo 'fprintf'ing 4096 byte il buffer verrà svuotato sul disco che potrebbe causare la latenza. Non puoi esternalizzare la registrazione effettiva in un thread separato? Codificare i messaggi di log e rimuoverli dal logthread. – Ctx

+0

Questo codice è in esecuzione come parte di un normale processo? Controlla qualsiasi mutex, semaforo, ecc. Che bloccherebbe un driver di dispositivo? – wallyk

+0

@jekso: crea un thread di registrazione (p) e usa qualcosa come un doppio elenco collegato come coda (accodamento in testa, eliminazione della coda alla fine) e pthread_cond_wait/notifica per segnalare nuove voci. – Ctx

risposta

2

Utilizzando fprintf è un dissipatore di tempo enorme, in particolare per i/T registrazione R. Effettua il logging in binario e scrivi un'utilità per stamparlo in un secondo momento.

Invece di:

fprintf(file,"%.2f %.2f %.2f",data1,data2,data3); 

Do:

fwrite(&data1,sizeof(double),1,file); 
fwrite(&data2,sizeof(double),1,file); 
fwrite(&data3,sizeof(double),1,file); 

Ancora meglio:

struct data { 
    double data1; 
    double data2; 
    double data3; 
    time_t event_time; 
    ... 
}; 

struct data data; 

fwrite(&data,sizeof(struct data),1,file); 

Se è ancora troppo lento, aggiungere lo struct a una coda anello e avere un thread separato scrivere le voci.

Se la scrittura del disco non può tenere il passo con le [ora] dati binari, mantenere la coda di anello e solo scaricare la coda di post-mortem se si rileva un errore fatale


Inoltre, in considerazione utilizzando mmap per accedere al file durante la scrittura. Vedere la mia risposta [con parametri di riferimento] qui: read line by line in the most efficient way *platform specific*

+0

Questo non risolverà il problema sottostante, ma diminuirà le sue occorrenze forse di un fattore 4 o 10, ma si verificherà ancora. Un meccanismo più semplice per fare la stessa cosa è chiamare ['setvbuf()'] (http://man7.org/linux/man-pages/man3/setbuf.3.html) con un buffer di grandi dimensioni (come 16 megabyte) assegnato . – wallyk

+0

Grazie per la risposta. Quindi 'fwrite' sarebbe intrinsecamente più veloce, anche se sta ancora scrivendo su un file nel bel mezzo del mio processo in tempo reale? Modifica: ho appena visto il commento di wallyk sopra e questo è quello che mi preoccupava. Ho diminuito la quantità di dati scritti alcune volte e solo diminuito la frequenza dei picchi di latenza, ma non li ho eliminati del tutto. – jekso

+0

Sì. 'fprintf' è _molto_ lento (ad esempio 100x più lento), in particolare con virgola mobile. Ho spedito sistemi di produzione R/T con requisiti di registrazione simili, quindi sto parlando per esperienza qui. Se, dopo aver eseguito la scrittura binaria sul file change, se è ancora troppo lento, scrivere i dati su un buffer della memoria e scaricare le ultime N voci quando si rileva un errore –

Problemi correlati