9

Memory management is a service provided by underlying operating system. When we call malloc()/free() and there's no operating systems running(for example a bare metal embedded system), how is the memory allocation and tracking handled?

There should be an entity that tracks which addresses are free and which are not. That's OS memory management unit. malloc()/free() will then have to call OS system calls. So no OS means no malloc()/free(). Am I wrong in assuming this?

Update:

All answers pointed out that malloc/free can use either static pool allocation(when no OS is available) or use sbrk/brk which are kernel system calls. Question is how does the malloc/free knows if there's a kernel beneath or not?

Answer(see comment by "Kuba Ober" under his answer below):

malloc doesn't need to know anything, because the C library that you link your project with is specific to the target: if you develop for Linux, you use a C library for Linux, different than when you develop for OS X, or Windows, or bare bones ARM Cortex M0. Or, heck, barebones x86. It's people who write the C library that know how to implement it so that it works on the desired target. For example, a barebones C library for x86 would use EFI and ACPI to query the list of available blocks of RAM unused by hardware nor BIOS, and then use those in fulfilling allocation requests.

doubleE
  • 1,027
  • 1
  • 12
  • 32
  • `There should be an entity that tracks which addresses are free and which are not.` There is. If there is no OS you'd have to handle this yourself. – tkausl Nov 03 '18 at 18:00
  • 2
    For programs running under an OS the C library `malloc` and `free` make use of OS memory manager. Typically on start the program allocate some memory from process heap and manage it to small chunks upon program request. On a bare metal system the C library must manage the whole pool of device memory. – Frankie_C Nov 03 '18 at 18:01
  • 2
    Let clarify a point, C library can't be a standard one when running on bare metal, you should write/hack some code specific to your HW. To keep close to a more general approach you may fake an heap function to call from the C library to collect the whole memory pool, that will be managed with library `malloc` functions. – Frankie_C Nov 03 '18 at 18:09
  • That is valid even sometimes for computers *with* OS. MS-DOS before version 2 didn't even have memory management functions, still C compilers had `malloc` – tofro Nov 03 '18 at 18:24

3 Answers3

13

malloc() and free() do not require OS support. They can be (and often are!) implemented on bare-metal systems. For example, the Arduino library uses malloc() and free() to manage strings.

In hosted implementations (that is, an application running on an operating system), malloc() and free() will typically use operating system services to allocate new "hunks" of memory -- often as much as a few megabytes at a time -- and to return those hunks to the operating system when they are unused. Smaller allocations are handled by cutting those blocks of memory into the sizes needed by an application. This allows small allocations to be managed without the overhead of a system call.

In an unhosted implementation (like a bare-metal system), the application already has access to all memory in existence on the system, and can parcel out chunks of that memory however it likes.

At a lower level: both hosted and unhosted implementations of malloc() often work by treating each allocated or unallocated block of memory as an entry in a linked list. This is typically accomplished by storing a structure immediately before the start of each allocation, e.g.

struct malloc_block {
    struct malloc_block *prev, *next;
    size_t size;
    ...
    char allocation[];
};

and returning a pointer to allocation as the return value of malloc(). Functions like realloc() and free() can retrieve the structure by subtracting the size of the structure from a pointer to the allocation.

  • I didn't quite get it. You're saying there are 2 implementation of `malloc()`? In a bare metal system, what entity keeps track of memory and tells `malloc()` what is available? – doubleE Nov 04 '18 at 06:33
  • 2
    @Novice typically, the system builder does so, by explicitly identifying the address and length of RAM to be used as the 'free store', (heap), at link time. The C runtime library startup will 'format' this area as required by its specific implementation, raising whatever structs are required to operate the free store as required by the app. – Martin James Nov 04 '18 at 07:18
  • That struct looks like a doubly linked list to me. – Thorkil Værge Jun 19 '21 at 12:02
5

The Malloc/free function manage a pool of memory. These functions are generally not operating system services.

How then is that pool created?

On most systems, malloc calls operating system services to map pages into the the process address space to create and expand the memory pool. If you call malloc, and no memory is available, most implementations will call a system service to map more memory and expand the pool.

The malloc implementation needs to maintain data structures that keep track of what memory in the pool is free and what has been allocated. This is done in many different ways. It is not unusual for programmers to select a malloc/free combination that works best for them and link it into their application.

So, yes there is operating system involvement—generally.

But you asked about whether they can be implemented without an operating system.

Suppose you did:

   static char pool [POOLSIZE] ;

in your malloc implementation. Then you would not require a system service to create the pool during execution time. On the other hand, your pool has a fixed size.

user3344003
  • 20,574
  • 3
  • 26
  • 62
2

Generally speaking: no, or at least not at runtime, if we define runtime as the moments between main() entering and returning.

Suppose you implement malloc that operates on a fixed-size pool:

static char pool[MALLOC_POOL_SIZE];

void *malloc(size_t size) {
  …
}

void free(void *block) {
  …
}

Then, on both hosted- and unhosted implementations you have working dynamic memory allocation. On hosted implementations, the binary loader will ensure that there’s memory mapped behind the pool. On unhosted implementations, the linker will pre-locate the pool in available RAM, and linking will fail if the pool is too large.

So no, in general no OS involvement is needed once your code is running, but OS involvement is needed to get your code to run in the first place (if there is an OS).

And of course, “not needed” means not necessary, but doesn’t exclude OS support for dynamic memory allocation in a particular C runtime library. In most hosted runtimes, malloc uses a pool that’s dynamically expanded (and perhaps contracted) by invoking relevant OS APIs. On classic Unix, the expansion would be done via the brk syscall.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • Thanks for clear explanation. My question is if `malloc/free` is using `sbrk/brk` which are OS system calls, and your application is bare-metal, then there is no `sbrk/brk` to call inside `malloc/free`. So how does `malloc` know if it's running on OS or not? – doubleE Nov 05 '18 at 17:40
  • 1
    `malloc` doesn't need to know anything, because the C library that you link your project with is specific to the target: if you develop for Linux, you use a C library for Linux, different than when you develop for OS X, or Windows, or bare bones ARM Cortex M0. Or, heck, barebones x86. It's people who write the C library that know how to implement it so that it works on the desired target. For example, a barebones C library for x86 would use EFI and ACPI to query the list of available blocks of RAM unused by hardware nor BIOS, and then use those in fulfilling allocation requests. – Kuba hasn't forgotten Monica Nov 05 '18 at 18:43