mmap, brk and sbrk memory management calls in UNIX


Sign up for FREE 1 month of Kindle and read all our books for free.

Get FREE domain for 1st year and build your brand new site

In this article we will learn more Advanced Memory Allocation in Unix.

Let's begin with an interesting question then !!

Question

An example for memory management system call in unix is:

fork
sigaction
mmap
execve

It's great if you got the the answer.

It's great even if you didn't get it! Because you are continuing to read and you are ready to explore and find the right answer :)

Happy learning!!

  • brk and sbrk are basic memory management system calls used in Unix and Unix-like operating systems
  • These system calls are used to control the amount of memory allocated to the data segment of the process.These functions are typically called from a higher-level memory management library function such as malloc.
  • In the original Unix system, brk and sbrk were the only ways in which applications could acquire additional data space; later versions allowed this to also be done using the mmap call.

Changing the Space allocated dynamically

  • The brk and sbrk calls dynamically change the amount of space allocated for the data segment of the calling process.
  • The change is made by resetting the program break of the process, which determines the maximum space that can be allocated.
  • The program break is the address of the first location beyond the current end of the data region. The amount of available space increases as the break value increases.
  • The available space is initialized to a value of zero, unless the break is lowered and then increased, as it may reuse the same pages in some unspecified way.
  • The break value can be automatically rounded up to a size appropriate for the memory management architecture.

Overall Function signatures and behavior

sbrk is used to adjust the program break value by adding a possibly negative size, while brk is used to set the break value to the value of a pointer. Set increment parameter to zero to fetch the current value of the program break.

Upon successful completion, the brk subroutine returns a value of 0, and the sbrk subroutine returns the prior value of the program break (if the available space is increased then this prior value also points to the start of the new area). If either subroutine is unsuccessful, a value of βˆ’1 is returned and the errno global variable is set to indicate the error.

The mmap() function asks to map length bytes starting at offset offset from the file (or other object) specified by the file descriptor fd into memory, preferably at address start. This latter address is a hint only, and is usually specified as 0. The actual place where the object is mapped is returned by mmap().

What does brk( ) system call do?

The brk() function is used to change the space allocated for the calling process. The change is made by setting the process's break value to addr and allocating the appropriate amount of space. The amount of allocated space increases as the break value increases. The newly-allocated space is set to 0.
In general brk() asks the kernel to let you you read and write to a contiguous chunk of memory called the heap

NOTE- This function is not supported in AMODE 64.

If successful, brk() returns 0.

If unsuccessful, brk() returns -1 and sets errno to one of the following values:
Error Code
Description
ENOMEM
The requested change would allocate more space than allowed for the calling process.

How to use sbrk function in C language?

#include <stdio.h>
#include <unistd.h>


int
main(int argc, char *argv[])
{
    long int page_size = sysconf(_SC_PAGESIZE);
    printf("My page size: %ld\n", page_size);
    void* c1 = sbrk(0);
    printf("program break address: %p\n", c1);
    printf("sizeof char: %lu\n", sizeof(char));
    c1 = (void*) ((char*) c1 + 1);
    printf("c1: %p\n", c1);
    brk(c1);
    void* c2 = sbrk(0);
    printf("program break address: %p\n", c2); 

}

Explanation

  1. The brk() system call sets the program break to the location specified by end_data_segment. Since virtual memory is allocated in units of pages, end_data_segment is effectively rounded up to the next page boundary.
  2. Output for the corresponding problem will be
My page size: 4096
program break address: 0x55b0bc104000
sizeof char: 1
c1: 0x55b0bc104001
program break address: 0x55b0bc104001

This program is a demonstration of brk() working.You may feel it like a little bit tricky one and don't loose hope if you don't understand the whole lot of it.Keep learning :)

What does sbrk() system call do?

The sbrk() function is used to change the space allocated for the calling process. The change is made by adding incr bytes to the process's break value and allocating the appropriate amount of space.

If successful, sbrk() returns the previous break value.

If unsuccessful, sbrk() returns -1 and sets errno to one of the following values:
Error Code
Description
ENOMEM
The requested change would allocate more space than allowed for the calling process.

#include <unistd.h>

int brk(void* end_data_segment);
void *sbrk(intptr_t increment);

How to use sbrk function in C language?

#include <lclib.h>
#include <stdio.h>

int _mneed = 1024;       /* Define default size of sbrk area. */

main()
{
   int n;
   char *stg;

   for(n = 1; ; ++n){
      stg = sbrk(80);
      if (stg == (char *) -1) break;
   }
   printf("%d 80-byte blocks could be allocated by sbrk.\n", n);
   puts("To change the amount available to sbrk, pass "
          "the runtime option =/,");
   puts("replacing  with the size of the sbrk area.");
}

Explanation

  1. We know that sbrk allocates a block of memory of the size specified by bytes . The block is suballocated from an area allocated at program initialization.
  2. The size of this area is determined by the initial value of the external variable _mneed ; if this variable is not set, a default area of 100K is allocated the first time sbrk is called.
  3. Here we have initialized _mneed to 1024 there by defining the size of the block.The program prints the number of blocks that assigned by sbrk.

What does mmap() system call do?

MMAP is a UNIX system call that maps files into memory. It’s a method used for memory-mapped file I/O. It brings in the optimization of lazy loading or demand paging such that the I/O or reading file doesn’t happen when the memory allocation is done, but when the memory is accessed. After the memory is no longer needed it can be cleared with munmap call.

On success, mmap() returns a pointer to the mapped area.
On error, the value MAP_FAILED (that is, (void *) -1) is returned, and errno is set appropriately. On success, munmap() returns 0, on failure -1, and errno is set (probably to EINVAL).

#include <sys/mman.h> 

void *mmap(void *start, size_t length, int prot, int flags, 
           int fd, off_t offset); 


int munmap(void *start, size_t length); 

How to use mmap function in C language?

#include <stdio.h>
#include <sys/mman.h>

int main(){

    int N=5; // Number of elements for the array   
    int *ptr = mmap ( NULL, N*sizeof(int),
            PROT_READ | PROT_WRITE,
            MAP_PRIVATE | MAP_ANONYMOUS,
            0, 0 );
    if(ptr == MAP_FAILED){
        printf("Mapping Failed\n");
        return 1;
    }

    // Fill the elements of the array
    for(int i=0; i ");
    for(int i=0; i<N; i++){
        printf("[%d] ",ptr[i]);
    }

    printf("\n");
    int err = munmap(ptr, 10*sizeof(int));

    if(err != 0){
        printf("UnMapping Failed\n");
        return 1;
    }
    return 0;
}

Explanation

Here we are allocating memory to an array using mmap and we are trying to pront it.Let's take a look at the program.

  1. PROT_READ | PROT_WRITE protection for reading and writing to the mapped region. 2. MAP_PRIVATE | MAP_ANONYMOUS flag.
  2. MAP_PRIVATE is used because the mapping region is not shared with other processes.
  3. MAP_ANONYMOUS is used because here, we have not mapped any file.

NOTE

These functions are kept for historical reasons. It was part of the Legacy Feature in Single UNIX Specification, Version 2, but has been withdrawn and is not supported as part of Single UNIX Specification, Version 3. New applications should use malloc() instead of brk() or sbrk().

Applications :

  • Can be used to optimize memory of ML applications which require large amount of data.

Hope you had fun while going through this article :)