Linux Memory Management

Source: Internet
Author: User

Linux will virtualize its physical memory. Instead of addressing the physical memory directly, the process maintains a special virtual address space for each process by the Linux kernel. This address space is linear, starting at 0, to a maximum value. Virtual space is made up of many pages. The system architecture and model determine the size of the page (the page size is fixed), and the typical page size includes 4K (32-bit system) and 8K (64-bit system). Each page has only two states of invalid (invalid) and valid (valid),
A valid page (valid page) is associated with a physical page or some level two storage media, such as a swap partition or a file on the hard disk.
The invalid page (invalid page) is not associated, which means it is not assigned or used. Access to invalid pages throws a segment error.
The address space does not need to be contiguous. Although it is a linear address, there are actually many small, non-addressable areas in the middle. A process cannot access a page in level two storage unless the page is associated with a page in physical memory. If a process tries to access such a page, the Memory Management Unit (MMU) generates a page error (page fault).

Multiple pages in a virtual memory, even virtual address spaces belonging to different processes, may also be mapped to the same physical page. This allows different virtual address spaces to share (share) the data on the physical memory. The shared data may be read-only or readable and writable. When a process attempts to write a shared writable page, the other case is that the MMU intercepts the write and produces an exception, and in response, the kernel transparently creates a copy of the page for the process to write on. We refer to this method as a write-time copy (Copy-on-write) (COW).

The kernel organizes pages with some of the same characteristics into chunks (blocks), such as read and write permissions. These blocks are called memory regions, segments (segments), or mappings (mappings). Typical segments include:
1, the text segment contains a process code, strings, constants, and some read-only data. In Linux, the text segment is marked as read-only and is mapped directly from the target file (executable program or library file) to memory.
2, stack segments (stacks) consist of a process's execution stack, extending or shrinking as the stack's depth is dynamic. The execution stack includes the program's local variables (local variables) and the return value of the function.
3, data segment, also called Heap, contains the dynamic storage space for a process. This paragraph is writable, and its size can vary. This part of the space is often allocated by malloc.
The 4,BSS segment (BSS segment) contains global variables that are not initialized. These variables have special values depending on the C standard, usually 0.

Dynamic memory allocation
void malloc (size_t size);
void
calloc (size_t nr, size_t size);
void realloc (void ptr, size_t size);
void free (void *ptr);
malloc () Gets a size-sized area of memory and returns a pointer to the first address of that part of memory. The contents of this area of memory are undefined and do not consider themselves to be all 0. On Failure, malloc () returns null and sets the errno error value to Enomem.
Array allocation calloc Unlike malloc, the calloc assigns all of the regions initialized with 0. It is important to note that binary 0 and floating point 0 are not the same.
Adjust the allocated memory size realloc successfully called REALLOC () to change the size of the memory area pointed to by ptr into size bytes. It returns a pointer to the new space, which may no longer be PTR when trying to enlarge the memory block. Because there is a potential copy operation, if size is 0, the effect will be the same as if the PTR was raised with free ().

Calling free () frees the memory that PTR points to. However, PTR must be the return value of the previous call to malloc (), calloc (), or realloc (). That is, you cannot use free () to release part of the memory you are applying to, such as pointing a pointer to the middle of a space. PTR may be null at this time free () is returned without doing anything, so it is not necessary to check if PTR is null when it is called. Memory leaks and dangling pointers have two commonly used tools to help you solve these problems: Electric fence and Valgrind.

Data alignment (alignment) refers to the relationship between the data address and the hardware-determined block of memory. When the address of a variable is a multiple of its size, it is called Natural alignment (naturally aligned). POSIX1003.1D provides a function called posix_memalign (). BSD and SunOS provide the following interfaces: Valloc In addition to the standard types of alignment and memory allocations, alignment issues can also be extended. For example, the alignment problems of complex data types will be more complex than standard types.

Management of data segments

The start address space of the heap is determined by the operating system and the execution file size.
int brk (void addr);
void
sbrk (intptr_t increment);
Because malloc () and other methods are more powerful and easy to use, most programs do not use these interfaces directly. SBRK the name of the function in the old UNIX system, when the heap and stack were in the same segment. The allocation of dynamic memory in the heap grows from the bottom of the data segment, and the stack grows downward toward the heap from the top of the data segment. The dividing line of a heap and stack is called an interrupt (break) or breakpoint (break point). In a modern system, the data segment exists in its own memory map, and we still use breakpoints to mark the end address of the map. Calling BRK () sets the breakpoint (the end of the data segment) to the address of end. At the time of success, return 0. At the time of failure, return-1 and set errno to Enomem. Call SBRK () to add increment bytes to the end of the data segment, and increment can be positively negative. SBRK () returns the modified breakpoint. So, when increment is 0, it gets the address of the breakpoint now.

Anonymous Memory mappings
The GLIBC memory allocation uses data segments and memory mappings. The most classic way to implement malloc () is to divide the data segment into a series of blocks of power of size 2, returning the smallest conforming block to satisfy the request. Release simply marks the area as unused. If the adjacent partitions are free, they will be synthesized into a larger partition. If the top of the heap is empty, the system can use BRK () to reduce the breakpoint, make the heap shrink, and return the memory to the system. This algorithm is called the Partner memory allocation algorithm (BUDDYMEMORYALLOCATIONSCHEME). Its advantages are high speed and simplicity, and the disadvantage is that it produces two types of fragmentation.
1, internal fragmentation (Internal fragmentation) is generated when the memory block used is larger than the requested size.
2, the external fragment is the total amount of free memory that is sufficient to satisfy a request, but there is no single block of space that can be used to handle this request when it occurs. This can also lead to insufficient memory utilization (because a larger block may be allocated) or a failed allocation (if no optional blocks exist).
3, this algorithm causes the allocation of one memory to "Bolt" the other, causing glibc to return the freed memory to the system. Imagine two blocks in memory that have been allocated, block A and block B. Block A is exactly at the point of the breakpoint, Block B is just below a, even if release B, before A is released, glibc can not adjust the breakpoint accordingly.
GLIBC is not always trying to return space to the system. In general, the heap does not shrink after each release. GLIBC will maintain the freed memory for subsequent allocations. GLIBC reduces the size of the data segment only if the heap is significantly larger than the allocated memory.

For larger allocations, GLIBC does not use the heap but creates an anonymous memory map (anonymous memories Mapping) to meet the requirements. The anonymous memory map is similar to the file-based mapping discussed in chapter fourth, except that it is not file-based-so called "anonymous." In fact, an anonymous memory map is just a large chunk of memory that has been initialized with 0 for the user to use. You can think of it as a heap that is used for a separate allocation. Because the storage for this mapping is not heap-based, it does not fragment within the data segment.
Using anonymous mappings to allocate memory has the following benefits:
1, no need to care about fragmentation.
2, the size of the anonymous store map is resizable, you can set permissions, and you can accept suggestions like normal mappings.
3, each allocation exists in a separate memory map. There's no need to manage a global heap anymore.

There are two drawbacks to using anonymous mappings over heaps:
1, each memory map is an integer multiple of the page size. Memory space may be wasted.
2, creating a new memory map is larger than the load that returns memory from the heap, because using the heap involves almost no kernel operation. The smaller the distribution, the more obvious the problem is, and the smaller and more frequent requests are not involved.

Judging by their pros and cons, glibc malloc () uses data segments to satisfy small allocations, while anonymous memory mappings are used to satisfy large allocations. The tipping point is adjustable (see the Advanced Memory allocation section later in this chapter) and will vary with the glibc version. At present, the critical point is generally 128KB: smaller than 128KB allocations are implemented by the heap, correspondingly, larger by the anonymous memory mapping to achieve. Create and destroy system calls with the following system calls:
void mmap (void start, size_t length, int prot, int flags, int fd, off_t offset);
int Munmap (void *start, size_t length);

When the input FD is-1, the anonymous mapping is created, and on the BSD system it can be an FD that opens the/dev/zero device.

Advanced memory allocation
int mallopt (int param, int value);
Storage allocation operations are controlled and restricted by the parameters of the kernel, and programmers can modify these parameters. such as the maximum number of memory maps, the use of anonymous mapping or data segment of the threshold value, high-speed memory area, the size of the number of padding bytes.

size_t malloc_usable_size (void *ptr);
Query how many bytes are available in a piece of allocated memory.

int Malloc_trim (size_t padding);
When the call to Malloc_trim () succeeds, Force glibc to return all the freed dynamic memory to the kernel. The data segment shrinks as much as possible, but the padding bytes are preserved. And then returns 1. When failed, returns 0.

Debug memory allocation
Because just one environment variable can control debugging, you don't have to recompile your program. For example, you can simply execute the following command:
$MALLOCCHECK=1./rudder
If set to 0, all errors are ignored by the storage system. If it is set to 1, the information is output to the standard error output stderr. If set to 2, the process terminates immediately via abort ().

struct Mallinfo mallinfo (void);
The C standard library obtains statistical data about the dynamic storage allocation system, including the number of free blocks, the size of the anonymous mappings, the available block sizes, and so on.

Stack-based allocation
void * ALLOCA (size_t size);
The dynamic memory allocation in a stack does not have to release the allocated memory, and failure indicates a stack overflow. However, it is important to note:
1, if you want to make the code portable, you should avoid using Alloca ().
2, the memory obtained by ALLOCA () cannot be used as a parameter of a function call because the allocated memory block is stored as a parameter in the stack of the function.
On a Linux system, Alloca () is a very useful tool that is not recognized by people. It behaves exceptionally well (in various architectures, memory allocation via ALLOCA () is as simple as adding stack pointers), which is much better than malloc (). For smaller memory allocations under Linux, Alloca () can reap the thrill of performance.

The common use of alloca () is to temporarily copy a string, because this is a very demanding and efficient alloca () implementation, and the Linux system specifically provides strdup () to copy a given string to the stack.

C99 introduced a variable-length array (Vlas), and the length of the variable-length array is determined at run time, not at compile time. The main difference between alloca () and variable-length arrays is that the memory obtained through the former is always present during the execution of the function, and the memory obtained by the latter is released after the scope has been scoped. There are good and bad ways to do this. In the For loop, we want to free up space for Each loop to reduce the overhead of memory without any side effects (we don't want extra memory to always be occupied). However, if for some reason we want this space to be kept in the next round of loops, then using Alloca () is clearly more reasonable.

Choose an appropriate memory allocation mechanism
Allocation method Advantages Disadvantage
malloc () simple, convenient, most commonly returned memory for 0 initialization
Calloc () to make the array allocation easier, with 0 initialized memory in allocating non-array space is more complex
ReAlloc () Resizing the allocated space can only be used to adjust the size of the allocated space
BRK () and SBRK () allow deep control of the heap for most users too low-level
Anonymous memory maps are simple to use, shareable, allow developers to adjust protection levels and provide recommendations, Allocations that are suitable for large spaces are not suitable for small allocations. At best, malloc () automatically uses the anonymous memory map
Posix_memalign () allocated memory to align to any reasonable size relative to the new, so portability is a problem; it is not necessary to use
when the alignment requirements are not very urgent. Memalign () and Valloc () are more common than posix_memalign () on other UNIX systems and are not POSIX compliant, and have less control over alignment than Posix_memalign ()
Alloca () the fastest way to allocate Do not need to know the exact size, for small allocations are well suited to not return error messages, are not suitable for large allocations, do not perform well on some UNIX systems the
variable-length array is similar to Alloca (), but frees space when exiting this layer loop, rather than allocating the array only when the function returns. In some cases the release of Alloca () is more applicable, and there is no alloca () common in other Unix systems

Memory operation
Void memset (void s, int C, size_t n);
int memcmp (const void s1, const void s 2, size_t N);
void memmove (void DST, const void src, size_t n);
void
memcpy (void DST, const void src, size_t N);
void memchr (const void s, int C, size_t N);
void memfrob (void S, size_t N); The
C language provides many functions for memory operations. These functions are similar in function to string manipulation functions (such as strcmp () and strcpy ()), but they handle objects that are user-supplied memory areas rather than null-terminated strings. Note that these functions do not return an error message. Therefore, it is the programmer's responsibility to prevent errors, and if you pass the wrong memory area as parameters, you will undoubtedly get a segment error.

Memory lock
Linux implements the request page scheduling, which means that the page is exchanged from the hard disk when needed, and then swapped out when it is no longer needed. This makes the virtual address space of the process in the system not directly related to the actual physical memory size, while the swap space on the hard disk provides an illusion of nearly infinite physical memory, and in the following two scenarios, the application may want to affect the paging of the system:
1, deterministic (determinism) time-constrained applications need to determine the scheduling behavior of the page themselves. If some memory operations cause page faults-This can result in expensive disk operations-the application may exceed the required run time. If you can ensure that the required pages are always in memory and never swapped into the disk, the application can ensure that memory operations do not cause page faults, provide consistent, deterministic program behavior, and thus provide performance.
2, security If the memory contains private information, this information may end up being stored on the hard disk in an unencrypted manner by the page scheduler. For example, if a user's private key is normally saved on disk in an encrypted manner, a key backup that is unencrypted in memory may end up being saved in a swap file. In a highly security-focused environment, this may not be acceptable. Such an application can request that the key remain on the physical memory.

int Mlock (const void addr, size_t len);
int Mlockall (int flags);
int Munlock (const void
addr, size_t len);
int munlockall (void);
int Mincore (void start, size_t length, unsigned char VEC);
Because memory locking can affect the overall performance of a system-in fact, if too many pages are locked, memory allocation fails--linux limits the number of pages a process can lock. A process with Cap_ipc_lock permissions can lock any number of pages. A process that does not have this permission can only lock Rlimit_memlock bytes.

Speculative storage allocation strategy
Linux uses a speculative allocation strategy. When a process requests additional memory from the kernel-such as expanding its data segment, or creating a new memory map-the kernel makes an allocation commitment but does not actually give the process any physical storage. The kernel fulfills its commitment to allocate a piece of physical memory only when the process writes to the new "allocated to" memory area. The kernel does this by page, and requests page scheduling and copy-on-write when needed. Advantages of doing so:
1, delaying the memory allocation allows the kernel to defer most of the work to the last minute (when it does need to be allocated).
2, because requests are per-page allocation based on demand, physical storage is only consumed when physical memory is really needed.
3, the virtual memory allocated may be much larger than the actual physical memory, or even more than the available swap space. This feature is called excess Use (overcommitment).

The overage feature can be closed by modifying the profile/proc/sys/vm/overcommit_memory. If set to 2, the virtual memory is limited to a certain percentage of physical memory using a strict auditing (strict accounting) policy. The default is 50 because physical memory also needs to contain the kernel, page tables, system hold pages, lock pages, and so on.

Linux Memory Management

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.