我想在Windows上使用c ++创建一个虚拟分配器,它在硬盘上的文件上分配数据,以减少分配大对象时的物理内存使用量! 我不想在virtualAlloc中使用系统虚拟内存..我想在磁盘上创建一个文件并使用它来分配整个对象,然后将我需要的部分或对象移动到RAM中。
我尝试使用内存映射文件,但是我遇到了一些问题:我使用映射文件来分配向量元素,但是当我烘焙删除它们中的任何一个时,元素的地址发生了变化,我也找不到一种只在需要时映射对象的方法“在我的测试中我映射了整个文件”!
任何资源或开源项目都可以提供帮助???
答案 0 :(得分:3)
Google可以提供帮助。我在几年前实现了一个使用共享内存存储的自定义STL分配器。可以使用相同的技术来实现磁盘支持的分配器。我首先看一下this SourceForge project的灵感。
答案 1 :(得分:2)
您可以从Boost.Interprocess中找到灵感,它提供对memory mapped files的支持,以及allocators and containers对该内存的支持。
有关分配器设计的更多信息也可以在http://www.boost.org/doc/libs/1_37_0/doc/html/interprocess/architecture.html
找到答案 2 :(得分:1)
很抱歉,但您无法理解(虚拟)内存的工作原理。一方面你说“我想制作”自定义内存分配器“但没有占用内存中的大空间”但另一方面你会惊讶于“元素的地址发生了变化”。
这是非常值得期待的。要确保(逻辑)对象的地址不会更改,您必须将由该地址表示的内存保留在对象中。如果释放内存,则可以重用,地址也可以使用。如果地址被重用,则无法将对象翻页回该地址。
最终,这里的问题是地址和内存非常非常紧密地联系在一起。回收存储器意味着回收地址。
答案 3 :(得分:0)
来自http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=213
POSIX标头包括内存映射系统调用和数据结构。因为这个界面比Windows更直观,更简单,所以我将我的内存映射示例基于POSIX库。
mmap()系统调用:
caddr_t mmap(caddress_t map_addr,
size_t length,
int protection,
int flags,
int fd,
off_t offset);
让我们来看看每个参数的含义。
在下面的示例中,程序将在命令行中传递的文件的前4 KB映射到其内存中,然后从中读取int值:
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/types.h>
int main(int argc, char *argv[])
{
int fd;
void * pregion;
if (fd= open(argv[1], O_RDONLY) <0)
{
perror("failed on open");
return –1;
}
/*map first 4 kilobytes of fd*/
pregion=mmap(NULL, 4096, PROT_READ,MAP_SHARED,fd,0);
if (pregion==(caddr_t)-1)
{
perror("mmap failed")
return –1;
}
close(fd); //close the physical file because we don't need it
//access mapped memory; read the first int in the mapped file
int val= *((int*) pregion);
}
要取消映射映射区域,请使用munmap()函数:
int munmap(caddr_t addr, int length);
addr是未映射区域的地址。 length指定应该取消映射多少内存(您可以取消映射先前映射区域的一部分)。以下示例取消映射先前映射文件的第一个千字节。此次调用后,剩余的三个KB仍然会映射到进程的RAM:
munmap(pregion, 1024);
答案 4 :(得分:0)
解决这个问题的最佳方法可能不是返回大型对象的常规指针。只需返回小代理。这些代理对象实现较大对象的完整接口。但是,这些代理对象可以处理RAM或磁盘上的原始数据。代理在它们之间实现LRU机制以优化RAM使用。调用者永远不会看到这些代理的地址发生变化,也不会获得任何指向原始数据的指针。