在特定文件上禁用 Cache/Buffer (Linux)
Disable Cache/Buffer on Specific File (Linux)
我目前正在 Yocto Linux 构建中工作,并且正在尝试与 FPGA 上的硬件模块接口。这个块是模仿一个带有 FAT16 文件系统的 SD 卡;包含单个文件 (cam.raw)。该文件表示 FPGA 和 linux 系统之间的共享内存 space。因此,我希望能够将数据从 linux 系统写入此内存并取回 FPGA 可能做出的任何更改(目前,FPGA 只是从内存中获取部分数据 space并将 6 添加到 32 位字的 LSB,就像我写 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 card" (FPGA) 读取并将文件数据存储在内存中。我需要完全关闭它,这样所有的读取都会导致从 FPGA 读取;但我不确定缓冲发生在哪里或如何进行。
如有任何见解,我们将不胜感激! (请注意,我可以使用 mmap.flush() 将我从 python 写入的任何数据转储到 FPGA,但我需要反向刷新或其他方式让它重新读取文件数据到mmap!)
更新:
正如评论中所建议的,mmap 方法可能不是实现我需要的最佳方法。但是,我现在已经在 python 和 C 中都尝试过,但是使用基本的 I/O 函数(os.read/write in python,read/write in C) 使用 O_DIRECT 标志。对于 most 这些操作,我最终得到 errno 22。仍在调查这个....
在进行挖掘之后,我发现我在 O_DIRECT 标志上做错了什么。在我的 C 和 Python 版本中,我没有使用 memalign 来创建缓冲区,也没有执行块 reads/writes。这个post有很好的解释:
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;
}
这将适用于我的 purposes,我没有看如何进行正确的内存对齐以使用 Python 的 os.read/os.write 函数以类似的方式。
我目前正在 Yocto Linux 构建中工作,并且正在尝试与 FPGA 上的硬件模块接口。这个块是模仿一个带有 FAT16 文件系统的 SD 卡;包含单个文件 (cam.raw)。该文件表示 FPGA 和 linux 系统之间的共享内存 space。因此,我希望能够将数据从 linux 系统写入此内存并取回 FPGA 可能做出的任何更改(目前,FPGA 只是从内存中获取部分数据 space并将 6 添加到 32 位字的 LSB,就像我写 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 card" (FPGA) 读取并将文件数据存储在内存中。我需要完全关闭它,这样所有的读取都会导致从 FPGA 读取;但我不确定缓冲发生在哪里或如何进行。
如有任何见解,我们将不胜感激! (请注意,我可以使用 mmap.flush() 将我从 python 写入的任何数据转储到 FPGA,但我需要反向刷新或其他方式让它重新读取文件数据到mmap!)
更新:
正如评论中所建议的,mmap 方法可能不是实现我需要的最佳方法。但是,我现在已经在 python 和 C 中都尝试过,但是使用基本的 I/O 函数(os.read/write in python,read/write in C) 使用 O_DIRECT 标志。对于 most 这些操作,我最终得到 errno 22。仍在调查这个....
在进行挖掘之后,我发现我在 O_DIRECT 标志上做错了什么。在我的 C 和 Python 版本中,我没有使用 memalign 来创建缓冲区,也没有执行块 reads/writes。这个post有很好的解释:
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;
}
这将适用于我的 purposes,我没有看如何进行正确的内存对齐以使用 Python 的 os.read/os.write 函数以类似的方式。