我正在研究需要硬盘mmap文件的Linux程序,但我有一个问题,什么会使它失败。就像如果所有的内存都是碎片化的,每个只有200M,但是我想把一个文件映射到1000M的内存,它会成功吗??
还有一个问题,linux中是否有像Windows中那样的工具来回收内存,例如xp的内置工具。
谢谢。
mmap()
使用程序堆区域之外的地址,所以堆碎片不是问题,除非它会使堆占用更多空间,并减少映射的可用空间。
如果您有很多映射文件,您可能会在地址空间相对受限的32位系统上遇到碎片问题。在64位系统上,碎片不太可能是一个问题,因为即使在现有映射之间只有小区域可用,仍然有很多可用的连续地址空间,与现有映射相邻。
在32位系统上更常见的问题是地址空间太小,根本无法映射大文件。在4GB地址空间中,通常有2GB可供用户空间使用,另外2GB由内核保留。在可用的2GB空间中,您的映射必须与程序代码、堆栈(通常很小)和堆(可能很大)共享空间。
简而言之,如果文件太大,mmap()
通常会在32位系统上失败,但是在64位系统上,您不太可能有一个大到足以导致这个问题的文件。
如果您正在创建一个私有的写时拷贝映射,它也可能由于缺乏交换空间而失败。内核必须确保可用RAM和交换空间的总和足够大,以容纳映射的大小,以防您修改所有页面,从而迫使内核对所有页面进行私有复制。共享映射不应该有这个问题,因为可以将更改刷新到磁盘上的文件,然后如果内存不足,可以丢弃页面,稍后从磁盘重新加载。
当然,如果您没有访问文件的权限,或者如果它不是可以映射的文件类型(例如目录或套接字),映射也可能失败。
我不清楚你说的回忆是什么意思。请记住,mmap()
消耗的稀缺资源不是内存,而是地址空间。你可以映射一个1GB的文件,即使机器实际上只有128MB的RAM,但是在32位系统上,你不能映射一个4GB的文件,即使机器有16GB的RAM。
虚拟内存的概念对于理解mmap()
的作用是必不可少的,所以如果您还不熟悉它,请阅读相关内容。
mmap
通过操作进程的页表来工作,页表是CPU用来映射地址空间的数据结构。CPU会根据内核设置的页表将"虚拟"地址转换为"物理"地址。
第一次访问映射内存时,CPU产生页面错误。然后,操作系统内核可以跳进去,通过分配内存和在新分配的缓冲区中进行文件I/O来"修复"无效的内存访问,然后继续执行程序,就像什么都没有发生一样。
如果你的进程地址空间不足, mmap
可能会失败,这对于32位代码来说是要小心的,因为所有可用的地址都可以很快地映射到大型数据集上。它也可能因为手册"错误"一节中提到的任何事情而失败。
如果内核在分配内存或执行I/O时出现问题,访问映射区域内的内存也可能失败。在这种情况下,您的进程将获得SIGBUS
信号。