我一直渴望得到一个STLish容器,我可以放入共享内存段或内存映射文件中.
我已经考虑使用自定义分配器和placement new将常规STL容器放入共享内存段.(像这篇ddj 文章).问题是STL容器内部会有指向他们拥有的内存的指针.因此,如果共享内存段或内存映射文件加载到不同的基址(可能在后续运行或第二个进程中),则内部指针突然无效.据我所知,自定义分配器方法只有在您始终可以将内存段映射到同一地址的进程时才有效.至少对于内存映射文件,我有很多经验,如果你只是让系统将它映射到感觉就好的地方.
我对如何做到这一点有一些想法,但如果其他人已经完成了这项工作,那我就想避免它(那就是我,懒惰).
我目前正在退出讨论,因为最好的锁定策略是高度依赖于应用程序的.
当使用共享存储器时,每个进程可以将共享区域映射到其相应地址空间的不同区域.这意味着在共享区域中存储指针时,需要将它们存储为共享区域起点的偏移量.不幸的是,这使得原子指令的使用变得复杂(例如,如果您正在尝试编写无锁算法).例如,假设您在共享内存中有一堆引用计数节点,由单个编写器创建.写入器周期性地原子地更新指针"p"以指向具有正引用计数的有效节点.读者希望原子地写入'p',因为它指向一个节点(结构)的开头,其第一个元素是引用计数.由于p始终指向有效节点,因此增加引用计数是安全的,并且可以安全地取消引用"p"并访问其他成员.但是,这一切只有在所有内容都在同一地址空间时才有效.如果节点和'p'指针存储在共享内存中,则客户端会遇到竞争条件:
在步骤2期间,p可能会改变,x可能不再指向有效节点.我能想到的唯一解决方法是以某种方式迫使所有进程就共享内存映射的位置达成一致,以便在mmap'd区域中存储真实指针而不是偏移量.有没有办法做到这一点?我在mmap文档中看到了MAP_FIXED,但我不知道如何选择一个安全的地址.
编辑:使用内联汇编和x86上的'lock'前缀也许可以建立一个"增量ptr X,偏移量Y乘以值Z"?其他架构的等价选项?没有写过很多装配,不知道是否存在所需的指令.
我正在寻找.NET的免费,完全托管的共享内存实现(P/Invoke是可以接受的,混合C++/CLI不是).
我尝试学习用c ++ 11的线程库编写并行代码所以首先我需要一个支持这个库的编译器我的问题是什么编译器可以支持c ++ 11的所有并发特性?
警告:
这个问题是关于c ++ 11的并发特性,而不是最适合C++ 11的编译器.
我正在尝试在以下类型的共享内存中构建映射
我像这样创建共享内存区域:
managed_shared_memory segment(create_only ,"MyMap" ,size);
ShMemAllocator_t alloc_inst (segment.get_segment_manager());
map = segment.construct<MyMap_t>("MyMap")
(std::less<int>()
,alloc_inst);
Run Code Online (Sandbox Code Playgroud)
地图中的值如下:
typedef pair<MutexType, boost::interprocess::offset_ptr<void> > ValueType ;
Run Code Online (Sandbox Code Playgroud)
MutexType本身是一个包含read和write mutex的结构(使用read_lock和write_lock); 定义如下:
typedef struct mutex_struct{
sharable_lock<interprocess_mutex> read_lock(interprocess_mutex, defer_lock);
scoped_lock<interprocess_mutex> write_lock(interprocess_mutex, defer_lock);
} MutexType;
Run Code Online (Sandbox Code Playgroud)
"size"是映射的总大小(就对象而言,所有void指针指向的数据大小的总和).
如何确保此void*数据也位于我创建的此内存段中,如何在现有共享内存区域中实例化它.之所以这样做,这是我想只有只是反复一次分配这个大的缓冲区删除/添加对象到它(地图模型高速缓存),我还没有在其中找到多个对象可以在相同的内存段内被分配办法在地图内.此外,寻求分配MutexType对返回编译错误,指出没有提供"call"操作符.
我已经实现了两个使用POSIX共享内存API共享数据的应用程序(即shm_open).一个进程更新存储在共享内存段中的数据,另一个进程读取它.我想使用某种互斥或信号量来同步对共享内存区域的访问.这样做最有效的方法是什么?我正在考虑的一些机制是
semget最近使用扩展pthreads工作,我发现了一个异常现象.我有一个内部状态的简单对象:
class Sum {
private $value = 0;
public function add($inc) { $this->value += $inc; }
public function getValue() { return $this->value; }
}
Run Code Online (Sandbox Code Playgroud)
现在我创建了一个Thread类,它对这个对象做了一些事情:
class MyThread extends Thread {
private $sum;
public function __construct(Sum $sum) {
$this->sum = $sum;
}
public function run(){
for ($i=0; $i < 10; $i++) {
$this->sum->add(5);
echo $this->sum->getValue() . " ";
}
}
}
Run Code Online (Sandbox Code Playgroud)
在我的main函数中,我创建了一个Sum对象,将其注入到线程中并启动它:
$sum = new Sum();
$thread = new MyThread($sum);
$thread->start();
$thread->join();
echo $sum->getValue();
Run Code Online (Sandbox Code Playgroud)
我期望结果是50,因为线程必须将值增加10倍.但是我得到了0! …
在Linux中,我想与其他进程共享我的进程的一些内存内容.其中一种方法是使用shm_open和mmap.如下.
/* Create a new memory object */
fd = shm_open( "/bolts", O_RDWR | O_CREAT, 0777 );
if( fd == -1 ) {
fprintf( stderr, "Open failed:%s\n",
strerror( errno ) );
return EXIT_FAILURE;
}
/* Set the memory object's size */
if( ftruncate( fd, sizeof( *addr ) ) == -1 ) {
fprintf( stderr, "ftruncate: %s\n",
strerror( errno ) );
return EXIT_FAILURE;
}
/* Map the memory object */
addr = mmap( 0, sizeof( *addr ),
PROT_READ | PROT_WRITE,
MAP_SHARED, …Run Code Online (Sandbox Code Playgroud) 我希望能够在不调用任何io的情况下将一系列文件内存映射归零(为了有效地顺序覆盖大文件而不会产生任何磁盘读取io).
这样做std::memset(ptr, 0, length)会导致页面从磁盘,如果他们已经不在,即使整个页面被覆盖从而完全捣毁磁盘性能存储器中读取.
我希望能够做一些类似于madvise(ptr, length, MADV_ZERO)将范围归零(类似于FALLOC_FL_ZERO_RANGE)的事情,以便在访问指定范围时导致零填充页面错误而不是常规的io页面错误.
遗憾的MADV_ZERO是不存在.即使相应的标志FALLOC_FL_ZERO_RANGE确实存在fallocate并且可以与其一起使用fwrite以实现类似的效果,尽管没有即时的交叉过程一致性.
我猜的一个可能的替代方案是使用MADV_REMOVE.但是,根据我的理解,这可能导致文件碎片并在完成时阻止其他操作,这使我不确定其长期性能影响.我对Windows的经验是,类似的FSCTL_SET_ZERO_DATA命令在调用时会引起显着的性能峰值.
我的问题是如何实现或模拟MADV_ZERO共享映射,最好是在用户模式下?
/dev/zero/我已阅读它被提出来简单地读取/dev/zero到所选择的范围.虽然我不太确定"阅读范围"意味着什么,以及如何做到这一点.难道喜欢一个fread从/dev/zero入内存范围?不确定如何避免访问时出现常规页面错误?
对于Linux,只需读
/dev/zero入所选范围即可.内核已经针对匿名映射优化了这种情况.如果一般来说这样做太难实现,我
建议MADV_ZERO应该有这样的效果:就像读取
/dev/zero到范围内一样,但总是有效的.
编辑:进一步跟踪线程,事实证明它实际上不起作用.
在处理共享映射时,它不会做任何技巧.
MADV_REMOVE在Linux中实现它的一个猜测(即不在我喜欢的用户应用程序中)可以通过简单的复制和修改MADV_REMOVE,即代替madvise_remove使用.虽然我在猜测这一点时有点头脑,特别是因为我不太清楚它周围的代码是做什么的:FALLOC_FL_ZERO_RANGEFALLOC_FL_PUNCH_HOLEvfs_allocate
// madvice.c
static long madvise_remove(...)
...
/*
* Filesystem's fallocate may need to take i_mutex. We need …Run Code Online (Sandbox Code Playgroud) 我正在寻找一种实现的数据结构List,允许我重用多个列表中出现的部分列表.
为了说明这一点,请考虑以下三个列表:
如您所见,红色序列(42, 88, 76, 60)和蓝色序列(21, 9, 47)多次使用,每个序列表示作为其他列表的一部分共享的独立列表.实际上,列表可能会更长.
该列表只需要是只读的,因为它将用作返回值.创建列表集合的过程将是唯一一个(允许)修改列表(使用add(..)操作等).共享部分列表将使得使用addAll(..)(内部使用System.arraycopy(..))扩展复制列表元素变得多余.
有没有轻量级的List实现来满足我的需求?或者有一个相对简单的方法来自己实现一个?