Domanda

Sto lavorando su un Linux embedded progetto di interfacce di un ARM9 a un codificatore video hardware del chip, e scrive il video su scheda SD o chiavetta USB.L'architettura del software comporta un driver del kernel che legge i dati in un pool di buffer, e userland app che scrive i dati in un file sul montata dispositivo rimovibile.

Mi sto trovando che al di sopra di un certo tasso di dati (circa 750kbyte/sec) inizio a vedere l'ambiente di video-scrittura app di stallo, forse per un secondo e mezzo, circa ogni 5 secondi.Questo è sufficiente a causare il driver del kernel per l'esecuzione di tamponi - e anche se non ho potuto aumentare il numero di buffer, il video deve essere sincronizzato (idealmente entro 40ms) con altre cose che stanno accadendo in tempo reale.Tra questi 5 secondi "picchi di lag", scrive la completa entro 40 ms (per quanto riguarda l'app è interessato - apprezzo sono tamponata dal sistema operativo)

Penso che questo lag spike è a che fare con il modo in cui Linux è lo svuotamento dei dati su disco - faccio notare che pdflush, la riscrittura è progettato per svegliarsi ogni 5s, la mia comprensione è che questo sarebbe quello che fa la scrittura.Non appena lo stallo è finito l'ambiente app è in grado di un servizio rapido e scrivere il portafoglio ordini del buffer (che non overflow).

Penso che il dispositivo che sto scrivendo è ragionevole ultimate throughput:copia di un file da 15 mb, una memoria fs e in attesa di sincronizzazione per completare (e la chiavetta usb la luce smette di lampeggiare) mi ha dato una velocità di scrittura di circa 2.7 Mb/sec.

Sto cercando due tipi di indizi:

  1. Come posso interrompere il burst, la scrittura di stallo la mia app - forse priorità di processo in tempo reale, le patch, la regolazione o il codice del filesystem di scrivere continuamente, piuttosto che burstily?

  2. Come posso rendere la mia app(s) consapevoli di ciò che sta succedendo con il filesystem in termini di scrittura backlog e della velocità effettiva della scheda/chiavetta?Ho la possibilità di modificare il video bitrate del codec hardware al volo che sarebbe molto meglio di eliminazione di fotogrammi, o l'imposizione di un artificiale cappuccio bitrate massimo autorizzato.

Qualche info in più:questo è un 200MHz ARM9 attualmente in esecuzione di un Montavista 2.6.10-basato su kernel.

Aggiornamenti:

  • Montare il filesystem di SINCRONIZZAZIONE cause throughput di essere troppo poveri.
  • I supporti rimovibili è FAT/FAT32 formattato e deve essere lo scopo della progettazione è che la media può essere collegato a qualsiasi PC Windows e leggere.
  • Regolarmente chiamata sync() o fsync() dire, ogni secondo cause regolare bancarelle e troppo poveri throughput
  • Sto utilizzando write() e open(O_WRONLY | O_CREAT | O_TRUNC) piuttosto che fopen (), etc.
  • Non riesco subito a trovare nulla on-line per il citato "Linux realtime filesystem".Link?

Spero che questo ha un senso.Primo Linux embedded domanda su stackoverflow?:)

È stato utile?

Soluzione

Per la cronaca, ci si è rivelato essere due aspetti principali, che sembrano aver eliminato il problema, ma in casi più estremi.Questo sistema è ancora in fase di sviluppo e non è stato accuratamente di tortura ancora testato, ma funziona abbastanza bene (tocco di legno).

La grande vittoria è venuto da rendere l'ambiente scrittore applicazione multi-threaded.È la chiamate write() che blocca a volte:altri processi e thread ancora eseguire.Così a lungo come ho un filo di manutenzione il driver del dispositivo e l'aggiornamento di telaio conti e da altri dati a sychronise con altre applicazioni che sono in esecuzione, i dati possono essere memorizzati nel buffer e scritto un paio di secondi dopo, senza rompere le eventuali scadenze.Ho provato con un semplice ping-pong doppio buffer prima, ma che non era sufficiente;piccolo buffer sarebbe sopraffatto e grandi, ha solo causato più pause durante il filesystem digerito la scrive.Un pool di 10 a 1 mb di buffer in coda tra i thread funziona bene ora.

L'altro aspetto è mantenere un occhio su ultimate scrivere il throughput di un supporto fisico.Per questo sto tenendo d'occhio le stat Sporco:segnalato da /proc/meminfo.Ho un po ' ruvido e pronto, codice motore encoder se Sporca:salite di sopra di una certa soglia, sembra vagamente di lavoro.Più il test e l'ottimizzazione necessaria in seguito.Per fortuna ho un sacco di RAM (128) per giocare mi dà un paio di secondi per vedere il mio portafoglio la costruzione e l'acceleratore giù senza problemi.

Cercherò di ricordare al pop indietro e aggiornare questa risposta se la trovo ho bisogno di fare altro per affrontare questo problema.Grazie agli altri utenti.

Altri suggerimenti

Cercherò di buttare fuori alcune proposte, consigli, è a buon mercato.

  • assicurarsi che si sta utilizzando un inferiore livello di API per la scrittura sul disco, non utilizzare in modalità utente funzioni di memorizzazione nella cache come fopen, fread, fwrite utilizzare il più basso livello di funzioni open, read, write.
  • passare il O_SYNC bandiera quando si apre il file, in questo modo ogni operazione di scrittura di un blocco fino a quando scritto su disco, che sarà rimuovere il bursty comportamento del vostro scrive...con le spese di ogni scrittura essere più lento.
  • Se si sta facendo una legge/ioctl da un dispositivo di afferrare un pezzo di video, dati, si potrebbe voler prendere in considerazione l'assegnazione di una regione di memoria condivisa tra l'applicazione e il kernel, altrimenti sono sempre a colpire con un mazzo di copy_to_user chiamate durante il trasferimento di dati video buffer del kernel di spazio in spazio utente.
  • Potrebbe essere necessario verificare che il dispositivo di memoria flash USB è abbastanza veloce, sostenuta trasferimenti per scrivere i dati.

Solo un paio di pensieri, spero che questo aiuta.

Qui alcune informazioni sull'ottimizzazione pdflush, la riscrittura per scrivere-operazioni pesanti.

Suona come si sta cercando di linux realtime filesystem.Essere sicuri di ricerca di Google et al per che.

XFS è in tempo reale, anche se non ho giocato con esso.

hdparm potrebbe consentono di disattivare la memorizzazione nella cache del tutto.

Tuning il filesystem opzioni (spegnere tutti gli extra non necessari attributi di file) potrebbe ridurre ciò che è necessario a filo, in questo modo si accelera lo svuotamento.Dubito che sarebbe di grande aiuto, però.

Ma il mio suggerimento sarebbe quello di evitare di usare il bastone come un filesystem a tutti e invece di usarlo come un dispositivo raw.Roba dati su di esso, come si farebbe con 'dd'.Poi altrove leggere che i dati grezzi e scrivono dopo la cottura.

Naturalmente, non so se questa è una opzione per voi.

Ha un supporto per il debug, si potrebbe usare strace per vedere che tipo di operazione richiede del tempo.Ci potrebbe essere qualche cosa che sorprende con la FAT/FAT32.

Scrivi in un unico file o in più file ?

Si può fare un thread di lettura, che sarà mantenere un pool di buffer video pronto per essere scritto in una coda.Quando un frame viene ricevuto, viene aggiunto alla coda, e il thread di scrittura è segnalato

Dati condivisa

empty_buffer_queue
ready_buffer_queue
video_data_ready_semaphore

La lettura del thread :

buf=get_buffer()
bufer_to_write = buf_dequeue(empty_buffer_queue)
memcpy(bufer_to_write, buf)
buf_enqueue(bufer_to_write, ready_buffer_queue)
sem_post(video_data_ready_semaphore)

Thread di scrittura

sem_wait(vido_data_ready_semaphore)
bufer_to_write = buf_dequeue(ready_buffer_queue)
write_buffer
buf_enqueue(bufer_to_write, empty_buffer_queue)

Se la scrittura filettato è bloccata in attesa del kernel, questo potrebbe funzionare.Tuttavia, se si sono bloccati all'interno della kerne spazio, quindi non c'è molto da fare, tranne cercando una versione più recente del kernel che il 2.6.10

Senza sapere di più circa le vostre particolari circostanze, posso solo offrire le seguenti ipotesi:

Provare a utilizzare fsync()/sync() per forzare il kernel per scaricare i dati sul dispositivo di memorizzazione più frequentemente.Sembra che il buffer del kernel tutti i tuoi scrive e poi collega il bus o altrimenti bancarelle di sistema durante l'esecuzione di scrittura effettiva.Con un'attenta chiamate a fsync() si può provare a pianificare scrive tramite il bus di sistema più a grana fine modo.

Potrebbe avere un senso per la struttura dell'applicazione, in modo che la codifica/capture (non hai parlato di acquisizione video, così sto facendo un'ipotesi qui - si potrebbe desiderare di aggiungere più informazioni) task viene eseguito nel proprio thread e buffer sua uscita in ambiente - poi, un secondo thread in grado di gestire la scrittura al dispositivo.Questo vi darà una lisciatura buffer per consentire l'encoder per finire sempre le sue scrive senza blocco.

Una cosa che sembra sospetto è che si vede solo questo problema in una certa data rate - se questo è stato davvero un problema di buffering, mi sarei aspettato il problema capita meno di frequente di dati a velocità inferiore, ma vorrei ancora aspettare per vedere questo problema.

In ogni caso, maggiori informazioni potrebbero rivelarsi utili.Qual è la tua architettura del sistema?(In termini molto generali.)

Date le ulteriori informazioni fornite, sembra che il dispositivo di throughput è piuttosto scarsa per piccole scrive e frequenti vampate di calore.Se sei sicuro che per i più grandi scrive si può ottenere una produttività sufficiente (e io non sono sicuro che sia il caso, ma il file system potrebbe essere facendo qualcosa di stupido, come l'aggiornamento di GRASSO dopo ogni scrittura), quindi avere una codifica filettatura di tubazioni di dati a un thread di scrittura con sufficiente buffer nel thread di scrittura per evitare di bancarelle.Ho usato la memoria condivisa ring buffer in passato per implementare questo tipo di regime, ma qualsiasi IPC meccanismo che consenta di lo scrittore a scrivere per il processo di I/O senza di stallo, a meno che il buffer è pieno dovrebbe fare il trucco.

Un utile Linux funzione e alternativa per la sincronizzazione o l'fsync è sync_file_range.Questo consente di pianificare i dati per la scrittura, senza aspettare che il buffer del kernel del sistema per ottenere intorno ad esso.

Per evitare lunghe pause, assicurarsi che il proprio IO in coda (per esempio:/sys/block/hda/coda/nr_requests) è abbastanza grande.La coda non è dove i dati va tra essere scaricate dalla memoria e arrivo sul disco.

Nota che sync_file_range non è portatile, e sono disponibili solo per i kernel 2.6.17 e versioni successive.

Mi è stato detto che dopo l'host invia un comando, MMC e SD card", che deve rispondere entro 0 a 8 byte".

Tuttavia, la spec permette queste carte a rispondere con "occupato" fino a quando non hanno completato l'operazione, e a quanto pare non c'è nessun limite per quanto tempo una carta può pretendere di essere occupato (per favore, la prego di dirmi se c'è un limite).

Vedo che alcuni di basso costo chip flash come il M25P80 hanno una garanzia di "limite massimo di singolo settore di cancellare il tempo" di 3 secondi, anche se in genere è "solo" richiede 0,6 secondi.

Che 0,6 secondi suona sospettosamente simile al tuo "stallo forse mezzo secondo".

Ho il sospetto che il compromesso tra basso, lento chip flash e costoso, veloce chip flash ha qualcosa a che fare con l'ampia variazione USB flash drive risultati:

Ho sentito voci che ogni volta che un settore flash viene cancellato e poi ri-programmato, ci vuole un po ' di più rispetto l'ultima volta.

Quindi, se avete un momento critico applicazione, potrebbe essere necessario (una) prova le vostre schede SD e chiavette USB per assicurarsi che essi soddisfano il requisito di latenza, banda, etc.richiesto dall'applicazione, e (b) peridically re-test o pre-emptive sostituire questi dispositivi di memoria.

Beh, ovvio che il primo, hai provato esplicitamente dicendo che il file di filo?Penso anche che ci potrebbe essere qualche ioctl è possibile utilizzare per farlo, ma, onestamente, non ho fatto molto C/POSIX file di programmazione.

Visto che stai su un kernel Linux si dovrebbe essere in grado di sintonizzare e ricompilare il kernel per qualcosa che si adatta alle vostre esigenze, ad esempio.molto più frequenti, ma anche più piccole vampate di memoria permanente.


Un rapido controllo per il mio uomo pagine di trovare questa:

SYNC(2)                    Linux Programmer’s Manual                   SYNC(2)

NAME
       sync - commit buffer cache to disk

SYNOPSIS
       #include <unistd.h>

       void sync(void);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       sync(): _BSD_SOURCE || _XOPEN_SOURCE >= 500

DESCRIPTION
       sync() first commits inodes to buffers, and then buffers to disk.

ERRORS
       This function is always successful.

Fare il flush()ing suoni giusto per me - si vuole essere in controllo, non lasciarlo in balia dei capricci del generico buffer layer.

Questo potrebbe essere ovvio, ma assicurarsi che non stai chiamando write() troppo spesso - assicurarsi che ogni write() dispone di dati sufficienti per essere scritto per rendere il syscall overhead pena.Inoltre, nell'altra direzione, non troppo di rado, o ti si blocca per un tempo sufficiente a causare un problema.

Più difficili da reimplementare traccia, hai provato a commutazione di i/o asincrono?Utilizzando aio si potrebbe sparare scrittura e la mano di un set di buffer mentre si sta succhiando i dati video in un altro set, e una volta completata la scrittura si passa imposta di buffer.

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