我在Linux上工作,需要硬盘中的mmap文件,但我有一个问题,什么会导致它失败。例如,如果所有的内存都是碎片化的,每个内存只有200M,但我想将一个文件映射到1000M的内存,会成功吗??
另一个问题是,linux中有没有像Windows中的一些工具一样的内存回收工具,例如xp的内置工具。
谢谢。
发布于 2011-05-04 10:51:26
mmap()使用程序堆区域之外的地址,所以堆碎片不是问题,除非它可以使堆占用更多的空间,并减少可用于映射的空间。
如果您有大量的映射文件,那么在地址空间相对受限的32位系统上,您可能会遇到碎片问题。在64位系统上,碎片不太可能成为问题,因为即使在现有映射之间只有很小的区域可用,在现有映射附近仍有大量连续的地址空间可用。
在32位系统上,更常见的问题是地址空间太小,根本无法映射大文件。在4 4GB的地址空间中,通常有2 4GB可用于用户空间,另外2 4GB由内核保留。在可用的2 2GB空间中,您的映射必须与程序的代码和堆栈(通常较小)和堆(可能较大)共享空间。
简而言之,如果文件太大,mmap()在32位系统上通常会失败,但在64位系统上,您不太可能拥有足够大的文件来导致该问题。
如果您正在创建私有的写入时复制映射,它也可能由于缺少交换空间而失败。内核必须确保可用RAM和交换空间的总和足够大,以容纳映射的大小,以防您修改所有页,从而强制内核制作所有页的私有副本。共享映射不应该有这个问题,因为可以将更改刷新到磁盘上的文件,然后如果内存不足,则可以丢弃页面,稍后再从磁盘重新加载。
当然,如果您没有访问该文件的权限,或者如果该文件不是可以映射的文件类型(如目录或套接字),映射也会失败。
不清楚你说的回忆是什么意思。请记住,mmap()消耗的稀缺资源不是内存,而是地址空间。即使机器实际只有128MB的RAM,也可以映射1 1GB的文件,但是在32位系统上,即使机器有16 1GB的RAM,也不能映射4 1GB的文件。
virtual memory的概念对于理解mmap()的作用至关重要,如果您还不熟悉它,请阅读它。
发布于 2011-05-04 11:10:52
mmap通过操作进程的页表来工作,页表是CPU用来映射地址空间的数据结构。CPU将执行translate "virtual" addresses to "physical" ones,并根据内核设置的page table执行此操作。
当您第一次访问映射内存时,您的CPU会生成一个page fault。然后,OS内核可以跳进去,通过分配内存和在新分配的缓冲区中执行文件I/O来“修复”无效的内存访问,然后继续执行程序,就像什么都没有发生一样。
如果您的进程地址空间不足,mmap可能会失败,这对于32位代码来说是值得注意的,因为在32位代码中,所有可用的地址都可以很快地映射到大型数据集。对于the manpage的“错误”部分中提到的任何事情,它也可能失败。
如果内核在分配内存或执行I/O时遇到问题,那么访问映射区域内的内存也会失败。在这种情况下,您的进程将获得SIGBUS signal。
发布于 2011-05-04 10:31:36
简短的答案是:视情况而定。
根据您拥有的内存量、正在工作的环境或访问映射的方式,mmap可能会失败的原因有很多。有关更多详细信息,请阅读mmap的手册页。
https://stackoverflow.com/questions/5877797
复制相似问题