44

事实证明,对 open() 与 fopen() 的整个误解源于 ARM 上的 Linux 2.6.14 内核中存在错误的 I2C 驱动程序。向后移植一个工作位 bashed 驱动程序解决了我试图在这里解决的问题的根本原因。

我试图找出 Linux (I2C) 中串行设备驱动程序的问题。看来,通过在设备上的写入和读取之间添加定时操作系统暂停(睡眠),事情会工作......(好多了)。

旁白:I2C 的本质是主机读取或写入的每个字节都由线路另一端(从机)上的设备确认 - 改善事情的暂停鼓励我将驱动程序视为异步工作 - 我无法与公共汽车的工作方式相协调。随便...

我想确保刷新写入(而不是使用固定持续时间的暂停),或者以某种方式测试写入/读取事务是否以多线程友好的方式 完成。

使用的问题fflush(fd);是它需要'fd'作为流指针(不是文件描述符),即

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

我的问题是我需要使用ioctl()不使用流指针的 。IE

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

建议?

4

6 回答 6

40

我想你正在寻找的可能是

int fsync(int fd);

或者

int fdatasync(int fd);

fsync会将文件从内核缓冲区刷新到磁盘。fdatasync除了元数据之外也可以。

于 2010-07-03T23:08:11.707 回答
29

你有两个选择:

  1. 用于获取与流指针fileno()关联的文件描述符stdio

  2. 根本不要使用<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);
于 2008-11-03T17:34:23.217 回答
12

fflush()仅刷新由对象fopen()管理的 stdio 层添加的缓冲。FILE *如内核所见,底层文件本身并未在此级别缓冲。这意味着使用和 raw绕过FILE *层的写入也不会以刷新的方式进行缓冲。fileno()write()fflush()

正如其他人指出的那样,尽量不要将两者混为一谈。如果你需要使用“原始”I/O 函数如ioctl(), 则open()直接自己创建文件,无需使用fopen<()stdio 的和朋友。

于 2008-11-04T07:32:32.477 回答
4

您是否尝试过禁用缓冲?

setvbuf(fd, NULL, _IONBF, 0);
于 2016-08-03T20:19:44.183 回答
2

如果您想反过来(将 FILE* 与现有文件描述符相关联),请使用 fdopen() :

                                                          FDOPEN(P)

NAME

       fdopen - associate a stream with a file descriptor

SYNOPSIS

       #include <stdio.h>

       FILE *fdopen(int fildes, const char *mode);
于 2008-11-04T14:14:12.200 回答
2

听起来您正在寻找的是 fsync() 函数(或 fdatasync()?),或者您可以在 open() 调用中使用 O_SYNC 标志。

于 2009-11-08T14:33:42.423 回答