【问题标题】:Disable Cache/Buffer on Specific File (Linux)禁用特定文件上的缓存/缓冲区 (Linux)
【发布时间】:2015-07-07 22:21:54
【问题描述】:

我目前正在使用 Yocto Linux 构建并尝试与 FPGA 上的硬件块进行交互。该块正在模仿带有 FAT16 文件系统的 SD 卡;包含单个文件 (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在这种情况下 -bit 字是 0x03020106)。然而,有人,无论是它的python还是linux或两者都在缓冲文件,而不是再次从“SD卡”(FPGA)读取并将文件数据存储在内存中。我需要完全关闭它,以便所有读取都会导致从 FPGA 读取;但我不确定缓冲发生在哪里或如何做到这一点。

任何见解将不胜感激! (注意,我可以使用 mmap.flush() 来获取我从 python 写入的任何数据以将其转储到 FPGA,但我需要像反向刷新或其他东西让它重新将文件数据读入 mmap!)

更新:

正如 cmets 中所建议的,mmap 方法可能不是实现我需要的最佳方法。但是,我现在已经在 python 和 C 中尝试过,但是使用 O_DIRECT 标志使用基本的 I/O 函数(python 中的 os.read/write,C 中的读/写)。对于大多数这些操作,我最终得到 errno 22。仍在研究这个....

【问题讨论】:

  • 我认为O_DIRECT 不会影响mmap()
  • 嗯,很高兴知道。那么有没有更好的方法来处理读取和写入? (不过我真的很喜欢 mmap 界面......)
  • 你在这里做了一些奇怪的事情:你在一个文件系统上正常挂载了一个文件,但是底层块设备的内容正在改变,没有人告诉内核块设备的内容已经改变。通常,当您将驱动器插入系统时,对驱动器的所有更改都会首先通过内核,因此它可以使所有缓存(谁知道有多少层缓存?)一直无效。您可以在/dev/mmcblk1 上尝试mmap(),自己解析文件系统,也可以请教内核专家。
  • O_DIRECT 不起作用的原因是因为O_DIRECT 基本上是一个绕过页面缓存的指令,而mmap() 是一个旨在将页面缓存暴露给您的程序的函数,所以它们在逻辑上是不兼容的。
  • mmap.flush 方法强制它将内存缓冲区与磁盘上的实际内容同步。但我不确定这是否足以解决您的问题 - 如果内存中的任何页面是脏的,它们将覆盖磁盘上的任何内容,而不是相反。

标签: python linux file hardware-programming fat16


【解决方案1】:

在进行挖掘之后,我发现我在使用 O_DIRECT 标志时做错了什么。在我的 C 和 Python 版本中,我没有使用 memalign 创建缓冲区,也没有进行块读取/写入。这篇文章有一个很好的解释:

How can I read a file with read() and O_DIRECT in C++ on 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;
}

这将适用于我的目的,我没有研究如何进行正确的内存对齐以以类似的方式使用 Python 的 os.read/os.write 函数。

【讨论】:

    猜你喜欢
    • 2011-09-01
    • 1970-01-01
    • 2011-12-18
    • 2013-08-14
    • 2013-09-19
    • 2012-11-24
    • 1970-01-01
    • 2012-03-04
    • 2019-07-19
    相关资源
    最近更新 更多