Отключить кэш / буфер для определенного файла (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 аналогичным образом.

Другие вопросы по тегам