How Memory Allocation Works on Linux

In a computer, for a process to be executable, it needs to be located in memory. For this, a field must be assigned to an in-memory process. Memory allocation is an important issue to keep in mind, especially in kernel and system architectures.

Let’s look at Linux memory allocation in detail and understand what goes on behind the scenes.

How is memory allocation done?

Most software engineers do not know the details of this process. But if you are a system programming candidate, you should know more about it. When looking at the allocation process, it is necessary to go into some small details about Linux and glibc library.

When applications need memory, they must request that memory from the operating system. This request from the kernel will naturally require a system call. You cannot allocate memory yourself in user mode.

The malloc() family of functions responsible for allocating memory in the C language. The question to ask here is whether malloc(), as a glibc function, makes a direct system call.

There is no system call called malloc in the Linux kernel. However, there are two system calls for application memory needs, which are brk and mmap.

Since you will be requesting memory in your application through glibc functions, you may be wondering which of these system calls glibc is using. The answer is both.


First system call: brk

Each process has a contiguous data field. With the brk system call, the program interrupt value, which defines the limit of the data field, is incremented and the allocation is performed.

Although allocating memory using this method is very fast, it is not always possible to return unused space to the system.

For example, consider that you allocate five fields, each 16KB in size, with a brk system call via the malloc() function. When you are done with two of these fields, the relevant resource (allocation) cannot be returned so that it can be used by the system. Because if you reduce the address value to show where your number two field starts, with a call to brk you will do the allocation for fields three, four, and five.

To avoid memory loss in this case, the malloc implementation in glibc monitors the allocated slots in the process data field and then assigns it back to the system using the free() function, so that the system can use free space for the next memory allocation.

In other words, after five 16KB regions have been allocated, if the second region is returned by free() and another 16KB region is requested again after some time, instead of expanding the data area through the call brk system, the previous address is returned.

However, if the requested new zone is larger than 16KB, the data area will be extended by allocating a new zone with the brk system call because zone two cannot be used. Although sector number two is unused, the application cannot use it because of the size difference. Because of situations like this, there is a situation called internal fragmentation, and in practice you can rarely make full use of all parts of the memory.

For better understanding, try to compile and run the following sample application:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char* argv[])
char *ptr[7];
int n;
printf("Pid of %s: %d", argv[0], getpid());
printf("Initial program break : %p", sbrk(0));
for(n=0; n<5; n++) ptr[n] = malloc(16 * 1024);
printf("After 5 x 16kB malloc : %p", sbrk(0));
printf("After free of second 16kB : %p", sbrk(0));
ptr[5] = malloc(16 * 1024);
printf("After allocating 6th of 16kB : %p", sbrk(0));
printf("After freeing last block : %p", sbrk(0));
ptr[6] = malloc(18 * 1024);
printf("After allocating a new 18kB : %p", sbrk(0));
return 0;

When you run the application, you will get an output similar to the following output:

Pid of ./a.out: 31990
Initial program break : 0x55ebcadf4000
After 5 x 16kB malloc : 0x55ebcadf4000
After free of second 16kB : 0x55ebcadf4000
After allocating 6th of 16kB : 0x55ebcadf4000
After freeing last block : 0x55ebcadf4000
After allocating a new 18kB : 0x55ebcadf4000

The output for brk with strace will be as follows:

brk(NULL)                               = 0x5608595b6000
brk(0x5608595d7000) = 0x5608595d7000

You can see, 0x21000 has been added to the end address of the data field. You can understand this from the value 0x5608595d7000. So about 0x21000or 132KB of allocated memory.

There are two important points to consider here. The first is to allocate more than specified in the sample code. Another line is which line of code caused the call to brk that provided the allocation.

Address space layout randomization: ASLR

When you run the above example application in turn, you will see different address values ​​each time. Making the address space change randomly in this way greatly complicates the work of security attacks and increases the security of the software.

However, in 32-bit architecture, eight bits are often used to randomize the address space. Increasing the number of bits will not be appropriate because the addressable area on the remaining bits will be very low. Also, using only 8-bit combinations should not pose a problem for an attacker.

On the other hand, in a 64-bit architecture, since so many bits can be allocated for an ASLR operation, much greater randomness is provided and a level of security is increased.

The Linux kernel also powers Android-based devices, and the ASLR feature is fully enabled on Android 4.0.3 and later. Even for this reason alone, it wouldn’t be wrong to say that 64-bit smartphones offer significant security advantages over 32-bit versions.

By temporarily disabling the ASLR feature with the following command, it seems that the previous test application returns the same address values ​​every time it is run:

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

To restore it to its previous state, simply write 2 instead of 0 in the same file.

Second system call: mmap

mmap is the second system call used to allocate memory on Linux. With the mmap call, the free space in any region of memory is mapped to the address space of the calling process.

In memory allocation done this way, when you want to return the second 16KB partition using the free() function in the previous brk example, there is no mechanism to prevent this operation. The relevant chunk of memory is removed from the process’s address space. It is marked as deprecated and returned to the system.

Because allocating memory with mmap is very slow compared to allocating brk, it is necessary to allocate brk.

With mmap, any free area of ​​memory is mapped to the process’s address space, so the contents of the allocated space will be reset before the process completes. If the reset is not done this way, then data belonging to the previous process that used the relevant memory area can also be accessed by the next unrelated process. This makes it impossible for us to talk about security in the system.

Importance of memory allocation in Linux

Memory allocation is very important, especially in terms of optimization and security. As seen in the examples above, not fully understanding this can mean destroying the security of your system.

Even similar concepts like push and pop exist in many programming languages ​​based on memory allocation operations. The ability to use and master system memory well is essential both in embedded system programming and in developing a secure and optimized system architecture.

If you also want to get your hands on Linux kernel development, consider mastering the C programming language first.

programming language c

A brief introduction to the C . programming language

Continue reading How Memory Allocation Works on Linux

Sarah Ridley is an automatic aggregator of the all world’s media. In each content, the hyperlink to the primary source is specified. All trademarks belong to their rightful owners, all materials to their authors. If you are the owner of the content and do not want us to publish your materials, please contact us by email – The content will be deleted within 24 hours.

Related Articles

Back to top button