我使用mmap(只是尝试了解mmap如何工作)来分配96k匿名内存,但看起来它将96k分成64k和32k。但是当分配960k时,它只分配一个大小为960k的块。当solaris将分配内存分成几部分时? 代码:
#define PROT PROT_READ | PROT_WRITE
#define MAP MAP_ANON | MAP_PRIVATE
if ((src = mmap(0, 88304, PROT, MAP, -1, 0)) == MAP_FAILED)
printf("mmap error for input");
if ((src = mmap(0, 983040, PROT, MAP, -1, 0)) == MAP_FAILED)
printf("mmap error for input");
if ((src = mmap(0, 98304, PROT, MAP, -1, 0)) == MAP_FAILED)
printf("mmap error for input");
桁架:
mmap(0x00000000, 88304, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0)
= 0xFFFFFFFF7E900000
mmap(0x00000000, 983040, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0)
= 0xFFFFFFFF7E800000
mmap(0x00000000, 98304, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0)
= 0xFFFFFFFF7E700000
PMAP:
FFFFFFFF7E700000 64 - - - rw--- [anon]
==> strange is that for 96k, it was broken into 2 part.
FFFFFFFF7E710000 32 - - - rw--- [anon]
FFFFFFFF7E800000 960 - - - rw--- [anon]
FFFFFFFF7E900000 64 - - - rw--- [anon]
FFFFFFFF7E910000 24 - - - rw--- [anon]
FFFFFFFF7EA00000 64 - - - rw--- [anon]
FFFFFFFF7EA10000 32 - - - rw--- [anon]
答案 0 :(得分:3)
是连续的内存,您可以通过地址(F...700000 + 64K = F...710000)
来判断,所以我认为您不必担心这一点。我很确定mmap需要在你的地址空间中为你提供连续的内存。否则它将毫无用处,因为它只给你一个基地址。有两个非连续的块,就没有办法找到第二个块。
所以我想你的问题是:为什么这会在pmap中显示为两个块?
我的回答是,“如果我知道就塞满了”。但我可以做出一个聪明的猜测,这是我在早上的这个时候(咖啡前)最好的希望。
我建议先将这些块分配给另一个进程(或两个),并将其释放回mmap内存管理器。我可以看到内存管理器如何合并块以创建更大的空闲块的两种可能性:
我怀疑后者只是因为内存管理器没有问题,为你的请求提供了两个块,所以它显然是为了处理它而构建的。 960K块可能没有分段,因为它来自一个更大的块。
请记住这是猜测(知情,但仍然是猜测)。我已经看到了很多UNIX的内部(真正的UNIX,而不是那个新的孩子:-)但我从来没有需要深入研究mmap。
答案 1 :(得分:3)
我不记得它的用语(条纹?切片?楔子?argh)但是Solaris从各种大小的池中分配不同的页面大小。事实证明这比统一页面大小更有效,因为它更好地使用了内存映射。其中一个尺寸是32K,另一个64K,另一个是1024K我相信。要获得96K,你得到64和32,得到960你得到1024K的大部分。
此魔法的核心资源是Solaris Internals本书。不幸的是,我的母亲在车库的一个盒子里。
答案 2 :(得分:0)
答案取决于你的意思是连续的。 Solaris和所有现代Unix和类Unix系统(可能都是现代操作系统)将物理内存划分为页面,“页面”内的内存将在物理层连续。大多数现代系统都有一个硬件MMU(内存管理单元),它将虚拟地址转换为物理地址。因此,mmap系统调用将返回一个连续的虚拟地址空间,但该虚拟地址将由MMU管理,MMU可能会使用多个页面,具体取决于页面的大小和内存映射的大小。
虽然所有虚拟地址都是连续的(在映射中) “页面”内的地址也将是物理上连续的,但页面和页面之间的过渡甚至可能在物理上彼此不相近。