我已经将mmap()与fopen("/dev/mem")一起使用,以创建到ARM系统中两个处理器内核之间共享的物理内存块的映射。 当运行 Linux 的处理器写入内存时,在另一个非 Linux 处理器看到写入数据之前可能会有一秒钟以上的滞后。 如果 Linux 进程在写入内存后立即调用此系统,则长时间的延迟会消失:
system("sync; echo 3 > /proc/sys/vm/drop_caches" );
我尝试直接在代码中复制该逻辑,但长时间的延迟仍然存在:
int fd;
char* data = "3";
sync();
fd = open("/proc/sys/vm/drop_caches", O_WRONLY);
write(fd, data, sizeof(char));
close(fd);
为什么 sync() 调用在行为上与同步系统命令不同? sync 命令是否会影响 sync() 调用不会的虚拟内存刷新?
我知道手册上说同步程序除了执行 sync(2) 系统调用之外什么都不做, 但是我从用户空间调用 sync() 的事实会影响它的行为吗? 它的行为就好像从用户空间调用同步只是安排同步而不是阻止直到其完成。
你忘了换行符。
echo 3
输出"3n"
.
此外,您正在采取一种异常迂回的路线来实现共享内存,并在此过程中给操作系统的其余部分带来巨大的成本。
每次调用 sync-the-command 或 sync-the-system-call 时,都会导致操作系统刷新整个计算机上的每个文件系统;更糟糕的是,你告诉操作系统忘记它拥有的每个文件系统缓冲区,迫使操作系统从磁盘重新读取所有内容。它对整个操作系统的性能几乎以你能想到的所有方式都是残酷的。
有一种更简单的方法。
使用 shm_open() 创建命名共享内存区域。使用 mmap 访问它。仅在该内存块上使用内存屏障或共享/命名互斥锁,以确保您可以一致且安全地读取和写入它。
就复杂性而言,您当前的方法可能比普通共享内存昂贵 1,000,000 倍。
drop_caches
和sync
在这里都不合适,因为它们都处理文件系统缓存 - 这实际上不是您在这里遇到的。sync
似乎解决了这个问题的事实可能是巧合。(它可能是在启动sync
工具时顺便刷新数据缓存。
您的应用程序很可能在系统上的两个处理器内核之间遇到缓存同步问题。尝试使用cacheflush()
系统调用来解决此问题:
#include <unistd.h>
#include <asm/unistd.h>
...
syscall(__ARM_NR_cacheflush, mapping_ptr, mapping_ptr + mapping_length, 0);
请注意,您可能需要刷新两个进程中的缓存才能看到正确的结果。
对于其他映射设备,通常需要刷新对映射内存的更改,但我认为在这种情况下可能不需要它。不过,尝试msync()
也无妨:
msync(mapping_ptr, mapping_length, MS_SYNC); // on process writing to memory
msync(mapping_ptr, mapping_length, MS_INVALIDATE); // on process reading from memory
最后,确保将此内存与MAP_SHARED
标志映射。