Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Linux/x86上,是从mmapping/dev/shm写回(WB)还是不可缓存写组合(WC)返回内存? 我有两个C++进程,它们通过内存映射的单一生产者-消费者(SPSC)进行通信。这些进程将仅在Linux/Intel x86-64上运行。语义是生产者填充前缓冲区,然后交换指针并更新计数器,让消费者知道它可以memcpy()后缓冲区。所有共享状态都存储在mmapped区域开始处的头块中 int\u fd; 易失性字符*\u映射缓冲区; ... _fd=shm|U open(“/dev/shm/ipc|u buffer”,O|u CREAT|O|u TRUNC|O|RDWR,S|irsr | S|u IWGRP | S|u IROTH | S|IWOTH); ... _mappedBuffer=静态强制转换(mmap(nullptr、大小文件字节、保护读取、保护写入、映射共享、映射无保留、映射填充、0));_Linux_X86 64_Shared Memory_Mmap_Memory Barriers - Fatal编程技术网

在Linux/x86上,是从mmapping/dev/shm写回(WB)还是不可缓存写组合(WC)返回内存? 我有两个C++进程,它们通过内存映射的单一生产者-消费者(SPSC)进行通信。这些进程将仅在Linux/Intel x86-64上运行。语义是生产者填充前缓冲区,然后交换指针并更新计数器,让消费者知道它可以memcpy()后缓冲区。所有共享状态都存储在mmapped区域开始处的头块中 int\u fd; 易失性字符*\u映射缓冲区; ... _fd=shm|U open(“/dev/shm/ipc|u buffer”,O|u CREAT|O|u TRUNC|O|RDWR,S|irsr | S|u IWGRP | S|u IROTH | S|IWOTH); ... _mappedBuffer=静态强制转换(mmap(nullptr、大小文件字节、保护读取、保护写入、映射共享、映射无保留、映射填充、0));

在Linux/x86上,是从mmapping/dev/shm写回(WB)还是不可缓存写组合(WC)返回内存? 我有两个C++进程,它们通过内存映射的单一生产者-消费者(SPSC)进行通信。这些进程将仅在Linux/Intel x86-64上运行。语义是生产者填充前缓冲区,然后交换指针并更新计数器,让消费者知道它可以memcpy()后缓冲区。所有共享状态都存储在mmapped区域开始处的头块中 int\u fd; 易失性字符*\u映射缓冲区; ... _fd=shm|U open(“/dev/shm/ipc|u buffer”,O|u CREAT|O|u TRUNC|O|RDWR,S|irsr | S|u IWGRP | S|u IROTH | S|IWOTH); ... _mappedBuffer=静态强制转换(mmap(nullptr、大小文件字节、保护读取、保护写入、映射共享、映射无保留、映射填充、0));,linux,x86-64,shared-memory,mmap,memory-barriers,Linux,X86 64,Shared Memory,Mmap,Memory Barriers,生产者需要一个StoreStore屏障,以确保在计数器递增之前交换是可见的,这在x86上应该是隐式的,具有回写(WB)内存: void product(){ ... //交换指针 char*tmp=_frontBuffer; _前缓冲区=_后缓冲区; _backBuffer=tmp; ... //此处是否需要SFENCE?如果WC不可缓存,则为是;如果WB由于x86订购保证,则为否? asm易失性(“sfence”:“内存”); _flipCounter++; } 消费者需要一个LoadLoa

生产者需要一个
StoreStore
屏障,以确保在计数器递增之前交换是可见的,这在x86上应该是隐式的,具有回写(WB)内存:

void product(){
...
//交换指针
char*tmp=_frontBuffer;
_前缓冲区=_后缓冲区;
_backBuffer=tmp;
...
//此处是否需要SFENCE?如果WC不可缓存,则为是;如果WB由于x86订购保证,则为否?
asm易失性(“sfence”:“内存”);
_flipCounter++;
}
消费者需要一个
LoadLoad
barrier if(WC)来确保在新的后缓冲区指针之前加载翻转计数器。如果内存为(WB),则我们知道CPU无法重新排序负载:

bool消费(uint64_t&localFlipVer,char*dst){
如果(本地FlipVer<\u flipCounter){
//此处需要LFENCE?如果WC不可缓存,则为是;如果WB由于x86订购保证,则为否?
asm易失性(“lfence”:“内存”);
std::memcpy(dst,_backBuffer,_bufferSize);
localFlipVer++;
返回true;
}
返回false;
}
我的问题和假设

内存映射区域是由mmapping
/dev/shm
写回返回的还是不可缓存的写组合返回的?如果是后者,则存储和加载是弱排序的,并且不遵循传统的x86排序保证(没有存储或加载重新排序)


因此,我必须使用
SFENCE
LFENCE
,而通常(使用WB),我可以只使用编译器屏障
asm volatile(“:”内存”)

/dev/shm/
只是一个
tmpfs
挂载点,就像
/tmp
一样

内存您
mmap
在文件中有正常的WB可缓存,就像
MAP\u ANONYMOUS
一样。它遵循普通的x86内存排序规则(程序顺序+带有存储转发的存储缓冲区),因此不需要SFENCE或LFENCE,只为acq_rel排序阻塞编译时重新排序。或者对于seq_cst、MFENCE或锁定操作,如使用
xchg
存储

对于无锁的类型,可以在指向SHM的指针上使用C11
函数。(通常为指针宽度的任意2次方大小。)

非无锁对象在执行操作的进程的地址空间中使用一个锁哈希表,因此单独的进程不会尊重彼此的锁。16字节对象可能仍然使用
锁cmpxchg16b
,它是无地址的,可以跨进程工作,即使GCC7和更高版本将其报告为非无锁,即使您使用
-mcx16
编译也是如此


我认为在主流Linux内核上,用户空间没有办法分配WB以外的任何类型的内存。(除了X服务器或直接渲染客户端映射视频RAM之外;我的意思是无法映射具有不同PAT内存类型的普通DRAM页面。)另请参见

对于不尝试将存储批处理到一个广泛的SIMD存储中的普通代码来说,WB以外的任何类型都将是一个潜在的性能灾难。e、 g.如果SHM中的数据结构受共享互斥体保护,那么如果关键部分中的正常访问不可缓存,那么它将非常糟糕。特别是在无争用的情况下,同一线程重复使用相同的锁并读取/写入相同的数据


所以它总是WB有很好的理由。

在哪里声明了
\u flipCounter
?它是一个结构的成员,用作MMMapped区域的头块。标题被重新解释到
\u mappedBuffer