0

I try to figure out the range of the shared memory segment i.e. the memory mapping segment in the memory layout of a process, from two sources below.


From https://manybutfinite.com/post/anatomy-of-a-program-in-memory/, I found a diagram of memory layout of a process

Do memory mapping segment and heap grow until they meet each other?

Or is there a limit for each of the two segments to grow up to, similar to RLIMIT_STACK for the stack segement?

enter image description here


From The Linux Programming Interface

To allow space for heap and stack growth, shared memory segments are attached starting at the virtual address 0x40000000 . Mapped mappings (Chapter 49) and shared libraries (Chapters 41 and 42) are also placed in this area. (There is some variation in the default location at which shared memory mappings and memory segments are placed, depending on the kernel versions and the setting of the process’s RLIMIT_STACK resource limit.) The address 0x40000000 is defined as the kernel constant TASK_UNMAPPED_BASE.

Does the shared memory segment start at TASK_UNMAPPED_BASE and grow upward?

Note that the previous diagram shows the shared memory segment grow downward, so does it grow upward or downward?

enter image description here

Thanks.

3

There are a couple of limits which apply to the mmap segment and the heap segment. RLIMIT_AS determines the available address space, overall; this covers all the memory allocations that a program can make. RLIMIT_DATA determines the maximum size of the data segment.

The kernel checks stack expansion, mmap, and brk (heap allocation) against these limits. It also checks allocations against potentially conflicting segments, so the segments never end up overwriting each other (see for example the checks performed for heap allocation with brk). If an allocation is impossible, the program is “informed” as appropriate: the C library returns an ENOMEM error for brk, the kernel kills the program with a SIGSEGV if the stack can’t be expanded...

How the shared memory segment (strictly speaking from the kernel perspective, virtual memory area) grows depends on the memory layout, which can very from one process to another. On most architectures, “legacy” memory maps result in bottom-up allocation, starting from TASK_UNMAPPED_BASE; non-legacy memory maps result in top-down allocation. See arch_pick_mmap_layout() and mmap_is_legacy() in the x86 architecture for an example. You can switch to the legacy memory map using setarch’s -L flag (see below for an example).

In practice, you can see how the segment grows by looking at /proc/$$/maps and checking the addresses of the loaded shared libraries (if any), v. their load order. The dynamic linker is always loaded first; if it has a lower address than other libraries, then allocation is bottom-up, otherwise it’s top-down. Compare the output of cat /proc/self/maps and setarch x86_64 -L cat /proc/self/maps on a 64-bit x86 system.

  • Thanks. (1) What is the value of RLIMIT_AS in the two diagrams? (2) if shared memory segment grows downward, what does TASK_UNMAPPED_BASE mean? (3) are shared memory segment and memory mapping segment the same concept? – Tim Sep 2 '18 at 21:10
  • Re. (2) and how the shared memory segment grows, there are differences between 32- and 64-bit x86, which I’ll check tomorrow. I’ll address all three questions then. – Stephen Kitt Sep 2 '18 at 21:18
  • (1) RLIMIT_AS doesn’t appear in the diagrams; it’s a limit which is checked before each allocation. (2) See my update. TASK_UNMAPPED_BASE is only relevant for bottom-up allocations. (3) The two segments aren’t the same concept but the end up in the same virtual memory area. – Stephen Kitt Sep 4 '18 at 8:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.