如何使用文件描述符刷新写入?

发布于 2024-07-07 14:13:00 字数 794 浏览 9 评论 0原文

事实证明,对 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

绮筵 2024-07-14 14:13:00

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

int fsync(int fd);

int fdatasync(int fd);

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

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.

郁金香雨 2024-07-14 14:13:00

您有两种选择:

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

  2. 根本不要使用 ,这样你就不需要担心刷新 - 所有写入都会立即发送到设备,对于字符设备, write() 调用甚至不会返回,直到较低级别的 IO 完成(理论上)。< /p>

对于设备级 IO,我想说使用 stdio 是非常不寻常的。 我强烈建议使用较低级别的 open()read()write() 函数(基于您稍后的回复) ):

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

You have two choices:

  1. Use fileno() to obtain the file descriptor associated with the stdio stream pointer

  2. Don'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 the write() 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);
春花秋月 2024-07-14 14:13:00

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

正如其他人指出的那样,尝试不要将两者混合。 如果您需要使用“原始”I/O 函数,例如 ioctl(),则直接自己open() 文件,无需使用fopen<() 和来自 stdio 的朋友。

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.

耶耶耶 2024-07-14 14:13:00

您是否尝试过禁用缓冲?

setvbuf(fd, NULL, _IONBF, 0);

Have you tried disabling buffering?

setvbuf(fd, NULL, _IONBF, 0);
樱&纷飞 2024-07-14 14:13:00

听起来您正在寻找的是 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.

踏月而来 2024-07-14 14:13:00

如果您想采取相反的方式(将 FILE* 与现有文件描述符关联),请使用 fdopen() :

                                                          FDOPEN(P)

NAME

       fdopen - associate a stream with a file descriptor

SYNOPSIS

       #include <stdio.h>

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

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文