How to Use the mmap Function to Write to the Memory in C

Mehvish Ashiq Feb 02, 2024
  1. the mmap() Function in C
  2. Use mmap() to Write to the Memory in C
How to Use the mmap Function to Write to the Memory in C

In this article, we’ll learn the mmap() function, how many parameters it takes, and how to use mmap() to write to the memory in C programming.

the mmap() Function in C

We use this function to map the process address space and either the devices or files. The mmap() function requests writeable anonymous and private mapping of memory’s n bytes.

The anonymous mapping and private mapping mean it is not backed by the file and is not shared with another process(s). To use the mmap(), we must include the header file.

#include <sys/mman.h>

It takes six arguments:

void *mmap(void *address, size_t length, int protect, int flags, int filedes,
           off_t offset)

Before going into the use of this function, let’s discuss the arguments.

  1. address - It provides the preferred starting address used for mapping. If there is no other mapping, the kernel will pick the nearby page boundary, creating a mapping.

    Else, the kernel will pick the new address. If the value for this parameter is NULL, the kernel will place the mapping where it sees fit.

  2. length - The bytes’ number is mapped.

  3. protect - It controls what type of access is allowed. For instance, the PROT_READ for reading access, the PROT_WRITE for write access, and the PROT_EXEC for execution.

  4. flags - It is used for controlling the map’s nature. Some of the common and useful flags are listed below:

    • MAP_SHARED - share mapping with other processes.
    • MAP_FIXED - The system is forced to use the same mapping address given via the address parameter.
    • MAP_ANONYMOUS / MAP_ANON - It creates anonymous mapping.
    • MAP_PRIVATE - The mapping would be private and not visible to others while using this flag.
  5. filedes - The file descriptor is supposed to be mapped.

  6. offset - The file mapping starts from this offset.

We get 0 if the mmap() successfully works. Otherwise, MAP_FAILED is returned.

Use mmap() to Write to the Memory in C

Let’s understand mmap() by practicing different examples.

Example Code (for memory allocation):

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

int main() {
  int N = 5;
  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;
  }

  for (int i = 0; i < N; i++) ptr[i] = i * 10;

  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;
}

Output:

[0] [10] [20] [30] [40]

We use the mmap() function to allocate the memory where we are using the PROT_READ | PROT_WRITE protections for writing & reading to a mapped region.

We use the MAP_PRIVATE flag because we don’t want to share the mapping region with other processes and the MAP_ANONYMOUS because we haven’t mapped the file.

The file descriptor and offset are set to 0 for the same cause.

Example Code (for interprocess communication):

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

int main() {
  int Number = 5;
  int *ptr = mmap(NULL, Number * sizeof(int), PROT_READ | PROT_WRITE,
                  MAP_SHARED | MAP_ANONYMOUS, 0, 0);

  if (ptr == MAP_FAILED) {
    printf("Mapping Failed\n");
    return 1;
  }

  for (int i = 0; i < Number; i++) {
    ptr[i] = i + 7;
  }

  printf("Initial array's values:");
  for (int i = 0; i < Number; i++) {
    printf(" %d", ptr[i]);
  }
  printf("\n");
  pid_t child_pid = fork();

  if (child_pid == 0) {
    // child
    for (int i = 0; i < Number; i++) {
      ptr[i] = ptr[i] * 5;
    }
  } else {
    // parent
    waitpid(child_pid, NULL, 0);
    printf("\nParent:\n");
    printf("Updated array's values:");
    for (int i = 0; i < Number; i++) {
      printf(" %d", ptr[i]);
    }
    printf("\n");
  }

  int err = munmap(ptr, Number * sizeof(int));

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

Output:

Initial array's values: 7 8 9 10 11
Initial array's values: 7 8 9 10 11

Parent:
Updated array's values: 35 40 45 50 55

We initialize the array with some values initially. Then, a child’s process changes the values.

Further, the values are read by the parent process, which was changed by the child process because the mapped memory is being shared with both (child & parent) processes. We are also using the munmap() to remove the memory mapping.

Mehvish Ashiq avatar Mehvish Ashiq avatar

Mehvish Ashiq is a former Java Programmer and a Data Science enthusiast who leverages her expertise to help others to learn and grow by creating interesting, useful, and reader-friendly content in Computer Programming, Data Science, and Technology.

LinkedIn GitHub Facebook

Related Article - C Function