问题
It turns out this whole misunderstanding of the open() versus fopen() stems from a buggy I2C driver in the Linux 2.6.14 kernel on an ARM. Backporting a working bit bashed driver solved the root cause of the problem I was trying to address here.
I\'m trying to figure out an issue with a serial device driver in Linux (I2C). It appears that by adding timed OS pauses (sleeps) between writes and reads on the device things work ... (much) better.
Aside: The nature of I2C is that each byte read or written by the master is acknowledged by the device on the other end of the wire (slave) - the pauses improving things encourage me to think of the driver as working asynchronously - something that I can\'t reconcile with how the bus works. Anyhoo ...
I\'d either like to flush the write to be sure (rather than using fixed duration pause), or somehow test that the write/read transaction has completed in an multi-threaded friendly way.
The trouble with using fflush(fd);
is that it requires \'fd\' to be stream pointer (not a file descriptor) i.e.
FILE * fd = fopen(\"filename\",\"r+\");
... // do read and writes
fflush(fd);
My problem is that I require the use of the ioctl()
, which doesn\'t use a stream pointer. i.e.
int fd = open(\"filename\",O_RDWR);
ioctl(fd,...);
Suggestions?
回答1:
You have two choices:
Use
fileno()
to obtain the file descriptor associated with thestdio
stream pointerDon't use
<stdio.h>
at all, that way you don't need to worry about flush either - all writes will go to the device immediately, and for character devices thewrite()
call won't even return until the lower-level IO has completed (in theory).
For device-level IO I'd say it's pretty unusual to use stdio
. I'd strongly recommend using the lower-level open()
, read()
and write()
functions instead (based on your later reply):
int fd = open("/dev/i2c", O_RDWR);
ioctl(fd, IOCTL_COMMAND, args);
write(fd, buf, length);
回答2:
I think what you are looking for may be
int fsync(int fd);
or
int fdatasync(int fd);
fsync
will flush the file from kernel buffer to the disk. fdatasync
will also do except for the meta data.
回答3:
fflush()
only flushes the buffering added by the stdio fopen()
layer, as managed by the FILE *
object. The underlying file itself, as seen by the kernel, is not buffered at this level. This means that writes that bypass the FILE *
layer, using fileno()
and a raw write()
, are also not buffered in a way that fflush()
would flush.
As others have pointed out, try not mixing the two. If you need to use "raw" I/O functions such as ioctl()
, then open()
the file yourself directly, without using fopen<()
and friends from stdio.
回答4:
It sounds like what you are looking for is the fsync() function (or fdatasync()?), or you could use the O_SYNC flag in your open() call.
回答5:
Have you tried disabling buffering?
setvbuf(fd, NULL, _IONBF, 0);
回答6:
If you want to go the other way round (associate FILE* with existing file descriptor), use fdopen() :
FDOPEN(P)
NAME
fdopen - associate a stream with a file descriptor
SYNOPSIS
#include <stdio.h>
FILE *fdopen(int fildes, const char *mode);
来源:https://stackoverflow.com/questions/259355/how-can-you-flush-a-write-using-a-file-descriptor