Domanda

  

Si scopre che tutto questo malinteso tra open () e fopen () deriva da un driver I2C difettoso nel kernel Linux 2.6.14 su un ARM. Il backport di un driver con bit funzionante ha risolto la causa principale del problema che stavo cercando di risolvere qui.

Sto cercando di capire un problema con un driver di dispositivo seriale in Linux (I2C). Sembra che aggiungendo pause del sistema operativo a tempo (sleep) tra le scritture e le letture sul dispositivo le cose funzionino ... (molto) meglio.

  

A parte: La natura di I2C è che ogni byte letto o scritto dal master è riconosciuto dal dispositivo sull'altra estremità del filo (slave) - le pause che migliorano le cose mi incoraggiano a pensare al driver come lavorare in modo asincrono - qualcosa che non riesco a conciliare con il funzionamento del bus. Anyhoo ...

Vorrei svuotare la scrittura per essere sicuri (piuttosto che usare una pausa a durata fissa), o in qualche modo testare che il la transazione di scrittura / lettura è stata completata in modo amichevole multi-thread.

Il problema con l'utilizzo di fflush(fd); è che richiede che 'fd' sia un puntatore di flusso (non un descrittore di file), cioè

FILE * fd = fopen("filename","r+");
... // do read and writes
fflush(fd);

Il mio problema è che ho bisogno dell'uso di ioctl(), che non usa un puntatore di flusso. cioè.

int fd = open("filename",O_RDWR);
ioctl(fd,...);

Suggerimenti?

È stato utile?

Soluzione

Hai due scelte:

  1. Utilizza fileno() per ottenere il descrittore di file associato al stdio puntatore di flusso

  2. Non usare affatto <stdio.h>, in questo modo non dovrai nemmeno preoccuparti di svuotare - tutte le scritture andranno immediatamente sul dispositivo e per i dispositivi a caratteri la chiamata write() non lo farà persino tornare fino al completamento dell'IO di livello inferiore (in teoria).

Per IO a livello di dispositivo direi che è abbastanza insolito usare open(). Consiglio vivamente di utilizzare invece le funzioni di livello inferiore read(), <=> e <=> (in base alla risposta successiva):

int fd = open("/dev/i2c", O_RDWR);
ioctl(fd, IOCTL_COMMAND, args);
write(fd, buf, length);

Altri suggerimenti

Penso che ciò che stai cercando potrebbe essere

int fsync(int fd);

o

int fdatasync(int fd);

fsync scaricherà il file dal buffer del kernel sul disco. fdatasync farà anche eccezione per i metadati.

fflush() elimina solo il buffering aggiunto dal livello stdio fopen(), come gestito dall'oggetto FILE *. Il file sottostante stesso, come visto dal kernel, non è bufferizzato a questo livello. Ciò significa che anche le scritture che ignorano il livello fileno(), usando write() e un ioctl() non elaborato, non sono memorizzate nel buffer in modo che open() svuoterebbe.

Come altri hanno sottolineato, prova a non mescolare i due. Se è necessario utilizzare & Quot; raw & Quot; Funzioni di I / O come fopen<(), quindi <=> direttamente il file, senza utilizzando <=> e gli amici di stdio.

Sembra che ciò che stai cercando sia la funzione fsync () (o fdatasync ()?), oppure potresti usare il flag O_SYNC nella tua chiamata open ().

Se vuoi fare il contrario (associa FILE * al descrittore di file esistente), usa fdopen ():

                                                          FDOPEN(P)

NAME

       fdopen - associate a stream with a file descriptor

SYNOPSIS

       #include <stdio.h>

       FILE *fdopen(int fildes, const char *mode);

Hai provato a disabilitare il buffering?

setvbuf(fd, NULL, _IONBF, 0);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top