Comment Pouvez-vous vider une écriture en utilisant un descripteur de fichier?
Il s'avère que tout ce malentendu entre open() et fopen () provient d'un pilote I2C bogué dans le noyau Linux 2.6.14 sur un ARM. Le Backporting d'un pilote bit bashed de travail a résolu la cause profonde du problème que j'essayais d'aborder ici.
J'essaie de résoudre un problème avec un pilote de périphérique série sous Linux (I2C). Il semble qu'en ajoutant des pauses timed OS (sleeps) entre les Écritures et les lectures sur l'appareil, les choses fonctionnent ... (beaucoup) mieux.
Mis à part: la nature de I2C est que chaque octet lu ou écrit par le maître est reconnu par l'appareil à l'autre extrémité du fil (esclave) - les pauses améliorant les choses m'encouragent à penser que le pilote fonctionne de manière asynchrone - quelque chose que je ne peux pas concilier avec le fonctionnement du bus. Anyhoo ...
Je voudrais soit vider l'écriture pour être sûr (plutôt que d'utiliser une pause de durée fixe), ou en quelque sorte tester que l'écriture / lecture la transaction a terminé de manière conviviale multi-thread.
Le problème avec l'utilisation de fflush(fd);
est qu'il nécessite que 'fd' soit un pointeur de flux (pas un descripteur de fichier), c'est-à-dire
FILE * fd = fopen("filename","r+");
... // do read and writes
fflush(fd);
Mon problème est que j'ai besoin de l'utilisation du ioctl()
, qui n'utilise pas de pointeur de flux. c'est à dire
int fd = open("filename",O_RDWR);
ioctl(fd,...);
Suggestions?
6 réponses
, Vous avez deux choix:
Utiliser
fileno()
pour obtenir le descripteur de fichier associé à lastdio
flux pointeurN'utilisez pas
<stdio.h>
du tout, de cette façon vous n'avez pas besoin de vous soucier de flush non plus - toutes les Écritures iront immédiatement à l'appareil, et pour les périphériques de caractères l'appelwrite()
ne reviendra même pas jusqu'à ce que l'E / S de niveau inférieur soit terminé (en théorie).
Pour les e / s au niveau de l'appareil, je dirais qu'il est assez inhabituel d'utiliser stdio
. Je voudrais fortement recommande d'utiliser le niveau inférieur open()
, read()
et write()
fonctionne à la place (en fonction de votre réponse ultérieure):
int fd = open("/dev/i2c", O_RDWR);
ioctl(fd, IOCTL_COMMAND, args);
write(fd, buf, length);
Je pense que ce que vous cherchez peut-être
int fsync(int fd);
Ou
int fdatasync(int fd);
fsync
videra le fichier du tampon du noyau sur le disque. {[3] } fera également l'affaire, sauf pour les méta-données.
fflush()
vide uniquement la mise en mémoire tampon ajoutée par la couche stdio fopen()
, telle que gérée par l'objet FILE *
. Le fichier sous-jacent lui-même, vu par le noyau, n'est pas mis en mémoire tampon à ce niveau. Cela signifie que les Écritures qui contournent la couche FILE *
, en utilisant fileno()
et un write()
brut, ne sont pas non plus tamponnées d'une manière que fflush()
viderait.
Comme d'autres l'ont souligné, essayez Pas de mélanger les deux. Si vous devez utiliser des fonctions d'E/S "brutes" telles que ioctl()
, alors open()
le fichier vous-même directement, sans en utilisant fopen<()
et amis de stdio.
On dirait que ce que vous cherchez est la fonction fsync () (ou fdatasync ()?), ou vous pouvez utiliser L'indicateur O_SYNC dans votre appel open ().
Si vous voulez aller dans l'autre sens (associer le fichier * au descripteur de fichier existant), utilisez fdopen ():
FDOPEN(P)
NAME
fdopen - associate a stream with a file descriptor
SYNOPSIS
#include <stdio.h>
FILE *fdopen(int fildes, const char *mode);
Avez-vous essayé de désactiver la mise en mémoire tampon?
setvbuf(fd, NULL, _IONBF, 0);