I've used mmap() with fopen("/dev/mem") to create a mapping to a block of physical memory shared between two processor cores in an ARM system. When the processor running Linux writes the memory, there can be a lag of over one second before the other non-Linux processor sees the written data. The long delay disappears if the Linux process makes this system call just after writing to memory:
我已经使用mmap()和fopen(“/ dev / mem”)来创建到ARM系统中两个处理器内核之间共享的物理内存块的映射。当运行Linux的处理器写入内存时,在其他非Linux处理器看到写入的数据之前,可能会有一秒钟的延迟。如果Linux进程在写入内存后立即调用此系统,则长时间延迟消失:
system("sync; echo 3 > /proc/sys/vm/drop_caches" );
I've tried to duplicate that logic directly in code, but the long delay persists:
我试图直接在代码中复制该逻辑,但长时间延迟仍然存在:
int fd;
char* data = "3";
sync();
fd = open("/proc/sys/vm/drop_caches", O_WRONLY);
write(fd, data, sizeof(char));
close(fd);
Why does the sync() call differ in behavior from the sync system command? Does the sync command effect virtual memory flushes that the sync() call does not?
为什么sync()调用的行为与sync system命令不同?同步命令会影响虚拟内存是否会刷新sync()调用?
I know the manual says that the sync program does nothing but exercise the sync(2) system call, but does the fact that I call sync() from userspace affect its behavior? It acts as though a call to sync from userspace merely schedules the sync rather than blocking until its completion.
我知道手册说同步程序除了执行sync(2)系统调用之外什么都不做,但是我从用户空间调用sync()会影响它的行为吗?它就好像从用户空间调用同步只是调度同步而不是阻塞直到完成。
2 个解决方案
#1
1
You forgot the newline.
你忘了换行了。
echo 3
outputs "3\n"
.
echo 3输出“3 \ n”。
Additionally, you are taking an exceptionally circuitous route to implementing shared memory, and imposing massive costs on the rest of the operating system in doing so.
此外,您正在采用异常迂回的方式来实现共享内存,并在此过程中对其余操作系统施加巨大成本。
Every time you call sync-the-command or sync-the-system-call, you cause the OS to flush every filesystem on the entire computer; worse, you're telling the OS to forget every filesystem buffer it has, forcing the OS to re-read everything from disk. It's atrocious to performance to the entire operating system in just about every way you can think of.
每次调用sync-the-command或sync-the-system-call时,都会导致操作系统刷新整个计算机上的每个文件系统;更糟糕的是,你告诉操作系统忘记它拥有的每个文件系统缓冲区,迫使操作系统重新读取磁盘上的所有内容。以您能想到的每一种方式对整个操作系统进行性能测试是非常糟糕的。
There is a much, much easier way.
有一种更容易的方式。
Use shm_open() to create a named shared memory region. Use mmap to access it. Use memory barriers or shared/named mutexes on just that chunk of memory to ensure that you can read and write it consistently and safely.
使用shm_open()创建命名的共享内存区域。使用mmap访问它。仅在该块内存上使用内存屏障或共享/命名互斥锁,以确保您可以一致且安全地读取和写入它。
In terms of complexity, your current approach is probably 1,000,000 times more costly than normal shared memory.
就复杂性而言,您当前的方法可能比普通共享内存高出1,000,000倍。
#2
0
Neither drop_caches
nor sync
are appropriate here, as both of them deal with file system caches - which aren't actually what you are running into here. The fact that sync
appears to solve it is probably coincidental. (It is probably incidentally flushing the data cache when the sync
tool is launched.)
这里没有drop_caches和sync是合适的,因为它们都处理文件系统缓存 - 这实际上并不是你在这里遇到的。同步似乎解决它的事实可能是巧合。 (启动同步工具时,可能会偶然刷新数据缓存。)
Your application is most likely running into cache synchronization issues across the two processor cores on your system. Try using the cacheflush()
system call to solve this:
您的应用程序很可能会遇到系统上两个处理器核心的缓存同步问题。尝试使用cacheflush()系统调用来解决此问题:
#include <unistd.h>
#include <asm/unistd.h>
...
syscall(__ARM_NR_cacheflush, mapping_ptr, mapping_ptr + mapping_length, 0);
Note that you will probably need to flush the cache in both processes to see the correct results.
请注意,您可能需要在两个进程中刷新缓存以查看正确的结果。
Flushing changes to mapped memory is often necessary for other mapped devices, but I think it may not be needed in this case. Trying an msync()
as well couldn't hurt, though:
对于其他映射设备,通常需要刷新对映射内存的更改,但我认为在这种情况下可能不需要。尽管如此,尝试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
Finally, make sure you are mapping this memory with the MAP_SHARED
flag.
最后,确保使用MAP_SHARED标志映射此内存。
#1
1
You forgot the newline.
你忘了换行了。
echo 3
outputs "3\n"
.
echo 3输出“3 \ n”。
Additionally, you are taking an exceptionally circuitous route to implementing shared memory, and imposing massive costs on the rest of the operating system in doing so.
此外,您正在采用异常迂回的方式来实现共享内存,并在此过程中对其余操作系统施加巨大成本。
Every time you call sync-the-command or sync-the-system-call, you cause the OS to flush every filesystem on the entire computer; worse, you're telling the OS to forget every filesystem buffer it has, forcing the OS to re-read everything from disk. It's atrocious to performance to the entire operating system in just about every way you can think of.
每次调用sync-the-command或sync-the-system-call时,都会导致操作系统刷新整个计算机上的每个文件系统;更糟糕的是,你告诉操作系统忘记它拥有的每个文件系统缓冲区,迫使操作系统重新读取磁盘上的所有内容。以您能想到的每一种方式对整个操作系统进行性能测试是非常糟糕的。
There is a much, much easier way.
有一种更容易的方式。
Use shm_open() to create a named shared memory region. Use mmap to access it. Use memory barriers or shared/named mutexes on just that chunk of memory to ensure that you can read and write it consistently and safely.
使用shm_open()创建命名的共享内存区域。使用mmap访问它。仅在该块内存上使用内存屏障或共享/命名互斥锁,以确保您可以一致且安全地读取和写入它。
In terms of complexity, your current approach is probably 1,000,000 times more costly than normal shared memory.
就复杂性而言,您当前的方法可能比普通共享内存高出1,000,000倍。
#2
0
Neither drop_caches
nor sync
are appropriate here, as both of them deal with file system caches - which aren't actually what you are running into here. The fact that sync
appears to solve it is probably coincidental. (It is probably incidentally flushing the data cache when the sync
tool is launched.)
这里没有drop_caches和sync是合适的,因为它们都处理文件系统缓存 - 这实际上并不是你在这里遇到的。同步似乎解决它的事实可能是巧合。 (启动同步工具时,可能会偶然刷新数据缓存。)
Your application is most likely running into cache synchronization issues across the two processor cores on your system. Try using the cacheflush()
system call to solve this:
您的应用程序很可能会遇到系统上两个处理器核心的缓存同步问题。尝试使用cacheflush()系统调用来解决此问题:
#include <unistd.h>
#include <asm/unistd.h>
...
syscall(__ARM_NR_cacheflush, mapping_ptr, mapping_ptr + mapping_length, 0);
Note that you will probably need to flush the cache in both processes to see the correct results.
请注意,您可能需要在两个进程中刷新缓存以查看正确的结果。
Flushing changes to mapped memory is often necessary for other mapped devices, but I think it may not be needed in this case. Trying an msync()
as well couldn't hurt, though:
对于其他映射设备,通常需要刷新对映射内存的更改,但我认为在这种情况下可能不需要。尽管如此,尝试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
Finally, make sure you are mapping this memory with the MAP_SHARED
flag.
最后,确保使用MAP_SHARED标志映射此内存。