Come si può svuotare una scrittura usando un descrittore di file?
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?
Soluzione
Hai due scelte:
-
Utilizza
fileno()
per ottenere il descrittore di file associato alstdio
puntatore di flusso -
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 chiamatawrite()
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);