事实证明,对open()与fopen()的整体误解源于ARM上Linux 2.6.14内核中的错误I2C驱动程序。向后移动一个工作位捣乱的驱动程序解决了我试图解决的问题的根本原因。
我正在尝试解决Linux(I2C)中串行设备驱动程序的问题。似乎通过在设备上的写入和读取之间添加定时OS暂停(休眠),事情起作用......(更好)。
除了: I2C的本质是主机读取或写入的每个字节都由线路另一端的设备(从机)确认 - 暂停改进的事情鼓励我将驱动程序视为异步工作 - 我无法调解总线工作方式。 Anyhoo ......
我要么刷新写入以确保(而不是使用固定的持续时间暂停), 或 以某种方式测试写/读事务以多线程友好的方式完成。
使用fflush(fd);
的麻烦在于它要求'fd'是流指针(不是文件描述符),即
FILE * fd = fopen("filename","r+");
... // do read and writes
fflush(fd);
我的问题是我需要使用ioctl()
,它不使用流指针。即。
int fd = open("filename",O_RDWR);
ioctl(fd,...);
建议?
答案 0 :(得分:30)
我认为您正在寻找的可能是
int fsync(int fd);
或
int fdatasync(int fd);
fsync
会将文件从内核缓冲区刷新到磁盘。除了元数据之外,fdatasync
也会这样做。
答案 1 :(得分:23)
您有两种选择:
使用fileno()
获取与stdio
流指针关联的文件描述符
根本不要使用<stdio.h>
,这样您也不必担心刷新 - 所有写入都会立即转到设备,对于角色设备write()
在较低级别的IO完成之前(理论上),调用甚至不会返回。
对于设备级IO,我会说使用stdio
是非常不寻常的。我强烈建议您使用较低级open()
,read()
和write()
函数(根据您之后的回复):
int fd = open("/dev/i2c", O_RDWR);
ioctl(fd, IOCTL_COMMAND, args);
write(fd, buf, length);
答案 2 :(得分:8)
fflush()
仅刷新由fopen()
对象管理的stdio FILE *
图层添加的缓冲。如内核所见,底层文件本身不会在此级别进行缓冲。这意味着使用FILE *
和原始fileno()
绕过write()
图层的写入也不会以fflush()
将刷新的方式进行缓冲。
正如其他人所指出的那样,尝试不混合两者。如果您需要使用ioctl()
之类的“原始”I / O功能,然后直接使用open()
文件,不使用使用fopen<()
和来自stdio的朋友。
答案 3 :(得分:2)
听起来你正在寻找的是fsync()函数(或fdatasync()?),或者你可以在open()调用中使用O_SYNC标志。
答案 4 :(得分:1)
如果你想反过来(将FILE *与现有文件描述符关联),请使用fdopen():
FDOPEN(P)
NAME
fdopen - associate a stream with a file descriptor
SYNOPSIS
#include <stdio.h>
FILE *fdopen(int fildes, const char *mode);
答案 5 :(得分:1)
您是否尝试过禁用缓冲?
setvbuf(fd, NULL, _IONBF, 0);