Отключить кэш / буфер для определенного файла (Linux)
В настоящее время я работаю в сборке Yocto Linux и пытаюсь взаимодействовать с аппаратным блоком на ПЛИС. Этот блок имитирует SD-карту с файловой системой FAT16; содержащий один файл (cam.raw). Этот файл представляет пространство разделяемой памяти между FPGA и системой linux. Таким образом, я хочу иметь возможность записывать данные из системы Linux в эту память и возвращать любые изменения, которые может внести FPGA (В настоящее время FPGA просто берет часть данных из пространства памяти и добавляет 6 к младшему разряду 32-битное слово, как будто я пишу 0x40302010 и должно вернуть 0x40302016, если я прочитаю данные). Однако из-за некоторого кеширования где-то, хотя я могу записать данные в FPGA, я не могу сразу получить результат.
В настоящее время я делаю что-то вроде этого (используя Python, потому что это легко):
% mount /dev/mmcblk1 /memstick
% python
>> import mmap
>> import os
>> f = os.open("/memstick/cam.raw", os.O_RDWR | os.O_DIRECT)
>> m = mmap.mmap(f, 0)
>> for i in xrange(1024):
... m[i] = chr(i % 256)
...
>> m.flush() # Make sure data goes from linux to FPGA
>> hex(ord(m[0])) # Should be 0x6
'0x0'
Я могу подтвердить с помощью dd, что данные изменяются (хотя я часто сталкиваюсь с проблемами буферизации и с этим) и использую инструменты для FPGA (SignalTap/ChipScope), что я действительно получаю правильный ответ (то есть, первое 32-битное слово в этом случае 0x03020106). Однако кто-то, будь то его python или linux или оба, буферизует файл и больше не читает с "SD-карты" (FPGA) и сохраняет данные файла в памяти. Мне нужно полностью отключить это, чтобы все чтения приводили к чтению из ПЛИС; но я не уверен, где происходит буферизация или как это сделать.
Любое понимание будет оценено! (Обратите внимание, я могу использовать mmap.flush(), чтобы взять любые данные, которые я пишу из python, чтобы выгрузить их в FPGA, но мне нужно как обратный сброс или что-то еще, чтобы он перечитал данные файла в mmap!)
Обновить:
Как предлагается в комментариях, подход mmap может быть не лучшим для реализации того, что мне нужно. Тем не менее, теперь я попробовал и на python, и на C, но с использованием основных функций ввода / вывода (os.read/write в python, чтение / запись в C) с использованием флага O_DIRECT. Для большинства из этих операций я получаю errno 22. Все еще изучаю это....
1 ответ
После копания я обнаружил, что я делаю неправильно с флагом O_DIRECT. В моих версиях C и Python я не использовал memalign для создания буфера и не делал блок чтения / записи. Этот пост имеет хорошее объяснение:
Как я могу прочитать файл с read() и O_DIRECT в C++ в Linux?
Итак, чтобы добиться того, что я делаю, эта программа на C работает в качестве основного примера:
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#define BLKSIZE 512
int main() {
int fd;
int x;
char* buf;
fd = open("/home/root/sd/fpga/cam.raw", O_RDWR | O_SYNC | O_DIRECT);
if (!fd) {
printf("Oh noes, no file!\n");
return -1;
}
printf("%d %d\n", fd, errno);
buf = (char*) memalign(BLKSIZE, BLKSIZE*2);
if (!buf) {
printf("Oh noes, no buf!\n");
return -1;
}
x = read(fd, buf, BLKSIZE);
printf("%d %d %x %x %x %x\n", x, errno, buf[0], buf[1], buf[2], buf[3]);
lseek(fd, 0, 0);
buf[0] = '1';
buf[1] = '2';
buf[2] = '3';
buf[3] = '4';
x = write(fd, buf, BLKSIZE);
printf("%d %d\n", fd, errno);
lseek(fd, 0, 0);
x = read(fd, buf, BLKSIZE);
printf("%d %d %x %x %x %x\n", x,errno, buf[0], buf[1], buf[2], buf[3]);
return 0;
}
Это будет работать для моих целей, я не смотрел, как сделать правильное выравнивание памяти, чтобы использовать функции os.read/os.write в Python аналогичным образом.