事实证明,对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,...);

建议?

有帮助吗?

解决方案

您有两种选择:

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

  2. 根本不要使用<stdio.h>,这样你也不必担心刷新 - 所有写入都会立即进入设备,对于角色设备,write()调用不会甚至返回,直到较低级别的IO完成(理论上)。

  3. 对于设备级IO,我会说使用open()非常不寻常。我强烈建议使用较低级别的read(),<=>和<=>函数(基于您以后的回复):

    int fd = open("/dev/i2c", O_RDWR);
    ioctl(fd, IOCTL_COMMAND, args);
    write(fd, buf, length);
    

其他提示

我认为您正在寻找的可能是

int fsync(int fd);

int fdatasync(int fd);

fsync将文件从内核缓冲区刷新到磁盘。除元数据外,fdatasync也会这样做。

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

正如其他人所指出的那样,尝试混合两者。如果你需要使用<!> quot; raw <!> quot; I / O函数,例如fopen<(),然后直接<=> >文件,使用<=>和stdio的朋友。

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

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

                                                          FDOPEN(P)

NAME

       fdopen - associate a stream with a file descriptor

SYNOPSIS

       #include <stdio.h>

       FILE *fdopen(int fildes, const char *mode);

您是否尝试过禁用缓冲?

setvbuf(fd, NULL, _IONBF, 0);
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top