Как вы можете очистить запись, используя файловый дескриптор? - PullRequest
32 голосов
/ 03 ноября 2008

Оказывается, все это непонимание между open () и fopen () проистекает из глючного драйвера I2C в ядре Linux 2.6.14 на ARM. Backporting работающего битового драйвера решил основную причину проблемы, которую я пытался устранить здесь.

Я пытаюсь выяснить проблему с драйвером последовательного устройства в Linux (I2C). Похоже, что при добавлении временных пауз ОС (снов) между записью и чтением на устройстве все работает ... (намного) лучше.

В стороне: Природа 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,...);

Предложения

Ответы [ 6 ]

30 голосов
/ 04 июля 2010

Я думаю, что вы ищете, может быть

int fsync(int fd);

или

int fdatasync(int fd);

fsync сбросит файл из буфера ядра на диск. fdatasync также подойдет, за исключением метаданных.

23 голосов
/ 03 ноября 2008

У вас есть два варианта:

  1. Используйте fileno() для получения дескриптора файла, связанного с указателем потока stdio

  2. Ни в коем случае не используйте <stdio.h>, поэтому вам не нужно беспокоиться о сбросе - все записи немедленно отправляются на устройство, а для символьных устройств вызов write() даже возвращайтесь, пока IO более низкого уровня не завершится (теоретически).

Для ввода-вывода на уровне устройства я бы сказал, что использовать stdio довольно необычно. Я настоятельно рекомендую использовать функции нижнего уровня open(), read() и write() (в зависимости от вашего более позднего ответа):

int fd = open("/dev/i2c", O_RDWR);
ioctl(fd, IOCTL_COMMAND, args);
write(fd, buf, length);
8 голосов
/ 04 ноября 2008

fflush() только очищает буферизацию, добавленную слоем stdio fopen(), как управляется объектом FILE *. Сам файл, как видно из ядра, не буферизуется на этом уровне. Это означает, что запись, что обход слоя FILE * с использованием fileno() и необработанного write(), также не буферизуется таким образом, что fflush() будет сбрасывать.

Как уже отмечали другие, попробуйте , а не , смешивая оба. Если вам нужно использовать «сырые» функции ввода / вывода, такие как ioctl(), то open() файл напрямую, без с использованием fopen<() и друзей из stdio.

2 голосов
/ 08 ноября 2009

Звучит так, будто вы ищете функцию fsync () (или fdatasync ()?), Или вы можете использовать флаг O_SYNC в вызове open ().

1 голос
/ 03 августа 2016

Вы пробовали отключить буферизацию?

setvbuf(fd, NULL, _IONBF, 0);
1 голос
/ 04 ноября 2008

Если вы хотите пойти другим путем (связать FILE * с существующим дескриптором файла), используйте fdopen ():

                                                          FDOPEN(P)

NAME

       fdopen - associate a stream with a file descriptor

SYNOPSIS

       #include <stdio.h>

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