如何使用文件描述符刷新写入?
事实证明,对 open() 与 fopen() 的整个误解源于 ARM 上的 Linux 2.6.14 内核中存在缺陷的 I2C 驱动程序。 向后移植一个工作位受到攻击的驱动程序解决了我在这里试图解决的问题的根本原因。
我正在尝试解决 Linux (I2C) 中串行设备驱动程序的问题。 看来,通过在设备上的写入和读取之间添加定时操作系统暂停(睡眠),事情会工作......(好多)更好。
旁白:I2C 的本质是主机读取或写入的每个字节都会由线路另一端的设备(从机)确认 - 暂停改进的情况鼓励我将驱动程序视为异步工作 - 我无法与总线的工作方式相协调。 无论如何...
我要么想刷新写入以确保(而不是使用固定持续时间的暂停),或 以某种方式测试写入/读取事务是否已以多线程友好的方式完成。
使用 fflush(fd); 的麻烦在于它要求“fd”是流指针(而不是文件描述符),即
FILE * fd = fopen("filename","r+");
... // do read and writes
fflush(fd);
我的问题是我需要使用 ioctl() ,它不使用流指针。 即
int fd = open("filename",O_RDWR);
ioctl(fd,...);
建议?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我认为您正在寻找的可能是
将
文件从内核缓冲区刷新到磁盘。 除了元数据之外,
fdatasync
也可以。I think what you are looking for may be
or
fsync
will flush the file from kernel buffer to the disk.fdatasync
will also do except for the meta data.您有两种选择:
使用
fileno()
获取与stdio
流指针关联的文件描述符根本不要使用
,这样你就不需要担心刷新 - 所有写入都会立即发送到设备,对于字符设备, write() 调用甚至不会返回,直到较低级别的 IO 完成(理论上)。< /p>对于设备级 IO,我想说使用
stdio
是非常不寻常的。 我强烈建议使用较低级别的open()
、read()
和write()
函数(基于您稍后的回复) ):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-levelopen()
,read()
andwrite()
functions instead (based on your later reply):fflush()
仅刷新由 stdiofopen()
层添加的缓冲,由FILE *
对象管理。 正如内核所见,底层文件本身并未在此级别进行缓冲。 这意味着使用fileno()
和原始write()
绕过FILE *
层的写入也不会以某种方式进行缓冲fflush()
会刷新。正如其他人指出的那样,尝试不要将两者混合。 如果您需要使用“原始”I/O 函数,例如
ioctl()
,则直接自己open()
文件,无需使用fopen<()
和来自 stdio 的朋友。fflush()
only flushes the buffering added by the stdiofopen()
layer, as managed by theFILE *
object. The underlying file itself, as seen by the kernel, is not buffered at this level. This means that writes that bypass theFILE *
layer, usingfileno()
and a rawwrite()
, are also not buffered in a way thatfflush()
would flush.As others have pointed out, try not mixing the two. If you need to use "raw" I/O functions such as
ioctl()
, thenopen()
the file yourself directly, without usingfopen<()
and friends from stdio.您是否尝试过禁用缓冲?
Have you tried disabling buffering?
听起来您正在寻找的是 fsync() 函数(或 fdatasync()?),或者您可以在 open() 调用中使用 O_SYNC 标志。
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.
如果您想采取相反的方式(将 FILE* 与现有文件描述符关联),请使用 fdopen() :
If you want to go the other way round (associate FILE* with existing file descriptor), use fdopen() :