tags:

views:

572

answers:

2

I used mmap(just try to understand how mmap works) to allocate 96k anonymous memory, but looks like it split the 96k into 64k and 32k. But when allocate 960k, it allocate only one chunk whose size is 960k. When solaris will split the allocate mem into several part? Code:

#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");

Truss:

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]
+2  A: 

That is contiguous memory, you can tell by the addresses (F...700000 + 64K = F...710000) so I don't think you have to worry about that. I'm pretty certain that mmap is required to give you contiguous memory in your address space. It would be pretty useless otherwise since it only gives you one base address. With two non-contiguous blocks, there would be no way to find that second block.

So I guess your question is: why does this show up as two blocks in the pmap?

To which my answer would be, "Stuffed if I know". But I can make an intelligent guess which is the best anyone can hope for from me at this time of the morning (pre-coffee).

I would suggest that those blocks had been allocated before to another process (or two) and had been released back to the mmap memory manager. I can see two possibilities on how that memory manager coalesces blocks to make bigger free blocks, either:

  • it does it as soon as the memory is released (not the case as your output shows that's not happening).
  • it does it periodically and it hadn't got around to it before you requested your 96K block; or
  • it doesn't bother at all because it's smart enough to do it during the allocation of a block to you.

I suspect it's the latter simply because the memory manager had no problems giving you two blocks for your request so it's obviously built to handle it. The 960K block is probably not segmented because it came from a much bigger block.

Keep in mind this is speculation (informed, but still speculation). I've seen quite a bit of the internals of UNIX (real UNIXes, not that new kid on the block :-) but I've never had a need to delve into mmap.

paxdiablo
As the address in the output of pmap is the virtual address of the process instead of the kernel, so no other process could release the block.
Daniel
+2  A: 

I can't remember the term for it (stripes? Slices? wedges? argh) but Solaris allocates different page sizes from pools of various sizes. This turns out to be somewhat more efficient than uniform page sizes, because it uses the memory mapping better. One of those sizes is 32K, another 64K, another is 1024K I believe. To get 96K, you got a 64 and a 32, to get 960 you got most of a 1024K.

The core resource for this wizardry is the Solaris Internals book. Mine, unfortunately, is in a box in the garage at the momrnt.

Charlie Martin