it-swarm.com.de

Wie kann ein Schreibvorgang mit einem Dateideskriptor gelöscht werden?

Es stellt sich heraus, dass dieses ganze Missverständnis von open () und fopen () von einem fehlerhaften I2C-Treiber im Linux 2.6.14-Kernel auf einem ARM herrührt. Durch das Zurückportieren eines funktionsfähigen bitbasierten Treibers wurde die Hauptursache des Problems behoben, das ich hier ansprechen wollte.

Ich versuche, ein Problem mit einem seriellen Gerätetreiber unter Linux (I2C) herauszufinden. Es scheint, dass durch das Hinzufügen von zeitgesteuerten OS-Pausen (Sleep) zwischen Schreiben und Lesen auf dem Gerät die Dinge besser funktionieren.

Nebenbei: Die Natur von I2C ist, dass jedes vom Master gelesene oder geschriebene Byte vom Gerät am anderen Ende des Kabels (Slave) bestätigt wird - die Pausen, die die Dinge verbessern, regen mich zum Nachdenken an Der Fahrer arbeitet asynchron - etwas, das ich nicht mit der Funktionsweise des Busses vereinbaren kann. Wie auch immer ...

Ich möchte entweder Flush den Schreibvorgang ausführen (anstatt eine Pause mit fester Dauer zu verwenden), oder Testen Sie irgendwie, ob die Schreib-/Lesetransaktion abgeschlossen auf eine multi-thread-freundliche Art und Weise ausgeführt wurde.

Das Problem bei der Verwendung von fflush(fd); ist, dass 'fd' ein Streamzeiger sein muss (kein Dateideskriptor), d. H.

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

Mein Problem ist, dass ich die Verwendung des ioctl() benötige, das keinen Stromzeiger verwendet. d.h.

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

Vorschläge?

35
Jamie

Sie haben zwei Möglichkeiten:

  1. Verwenden Sie fileno(), um den Dateideskriptor abzurufen, der dem Stream-Zeiger stdio zugeordnet ist

  2. Verwenden Sie überhaupt nicht <stdio.h>, Auf diese Weise müssen Sie sich auch nicht um Flush kümmern - alle Schreibvorgänge gehen sofort zum Gerät, und für Zeichengeräte wird der write() -Aufruf gewonnen ' t kehre sogar zurück, bis die untere Ebene IO abgeschlossen ist (theoretisch).

Für Geräteebenen IO Ich würde sagen, es ist ziemlich ungewöhnlich, stdio zu verwenden. Ich würde dringend empfehlen, die niedrigere Ebene open(), read() und write() funktionieren stattdessen (basierend auf Ihrer späteren Antwort):

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

Ich denke, was Sie suchen, kann sein

int fsync(int fd);

oder

int fdatasync(int fd);

fsync löscht die Datei aus dem Kernel-Puffer auf die Festplatte. fdatasync funktioniert auch mit Ausnahme der Metadaten.

33
Danke Xie

fflush() löscht nur die von der Ebene stdio fopen() hinzugefügte Pufferung, die vom Objekt FILE * verwaltet wird. Die zugrunde liegende Datei selbst wird auf dieser Ebene aus Sicht des Kernels nicht gepuffert. Dies bedeutet, dass Schreibvorgänge, die die Ebene FILE * Mithilfe von fileno() und einer unformatierten write() umgehen, ebenfalls nicht so gepuffert werden, wie dies bei fflush() der Fall wäre spülen.

Wie andere darauf hingewiesen haben, versuchen Sie nicht die beiden zu mischen. Wenn Sie "rohe" E/A-Funktionen wie ioctl() verwenden müssen, dann open() die Datei selbst, ohne mit fopen<() und freunde von stdio.

8
unwind

Haben Sie versucht, die Pufferung zu deaktivieren?

setvbuf(fd, NULL, _IONBF, 0);
2
rustyx

Es hört sich so an, als ob Sie nach der Funktion fsync () (oder fdatasync ()?) Suchen, oder Sie könnten das O_SYNC-Flag in Ihrem open () -Aufruf verwenden.

2
jstedfast

Wenn Sie umgekehrt vorgehen möchten (verknüpfen Sie FILE * mit dem vorhandenen Dateideskriptor), verwenden Sie fdopen ():

                                                          FDOPEN(P)

NAME

       fdopen - associate a stream with a file descriptor

SYNOPSIS

       #include <stdio.h>

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