Il s'avère que tout ce malentendu entre open () et fopen () provient d'un pilote buggy I2C dans le noyau Linux 2.6.14 sur un ARM. Le rétroportage d'un pilote en panne fonctionnant sur des bits a résolu la cause première du problème que j'essayais de résoudre 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 (mises en veille) du système d'exploitation chronométrées entre les écritures et les lectures sur l'appareil, les choses fonctionnent ... (beaucoup) mieux.
À 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 à le conducteur fonctionne de manière asynchrone - quelque chose que je ne peux pas concilier avec le fonctionnement du bus. Anyhoo ...
Je voudrais soit flush l'écriture pour être sûr (plutôt que d'utiliser une pause à durée fixe), ou teste en quelque sorte que la transaction d'écriture/lecture a terminée d'une 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 de la ioctl()
, qui n'utilise pas de pointeur de flux. c'est à dire.
int fd = open("filename",O_RDWR);
ioctl(fd,...);
Suggestions?
Vous avez deux choix:
Utilisez fileno()
pour obtenir le descripteur de fichier associé au pointeur de flux stdio
N'utilisez pas du tout <stdio.h>
, De cette façon vous n'avez pas non plus à vous soucier du vidage - toutes les écritures iront immédiatement sur le périphérique, et pour les périphériques de caractères, l'appel write()
ne sera pas même retourner jusqu'à ce que le niveau inférieur IO soit terminé (en théorie).
Pour le niveau de l'appareil IO je dirais qu'il est assez inhabituel d'utiliser stdio
. Je recommande fortement d'utiliser le niveau inférieur open()
, read()
et write()
à la place (sur la base 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. fdatasync
fera aussi l'affaire sauf pour les métadonnées.
fflush()
vide uniquement la 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 brut write()
, ne sont pas non plus mises en mémoire tampon d'une manière que fflush()
viderait.
Comme d'autres l'ont souligné, essayez pas 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.
Avez-vous essayé de désactiver la mise en mémoire tampon?
setvbuf(fd, NULL, _IONBF, 0);
Il semble que ce que vous recherchez soit la fonction fsync () (ou fdatasync ()?), Ou vous pouvez utiliser l'indicateur O_SYNC dans votre appel open ().
Si vous souhaitez inverser la procédure (associer FILE * 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);