Memory
CS 105 also covered memory management from a programmer's perspective.
Memory Management
Processes sometimes need to ask for more memory, and the operating system provides a way to do that. The operating system also provides a way to free memory that is no longer needed. The programmer uses system calls, such as malloc and free in C, to request or release memory.
But it turns out that the operating system doesn't want to get involved every time a program wants a tiny bit more memory, so malloc and free are actually implemented in the C library, and they use a system call to get a big chunk of memory from the operating system, and then manage that memory themselves.
Here is some example code that requests one megabyte of memory a little bit at a time:
#include <stdio.h>
#include <stdlib.h>
int main() {
// Allocate 1024 chunks, each of 1 KB of memory
void *ptrs[1024];
printf("Allocating memory...\n");
for (int i = 0; i < 1024; i++) {
ptrs[i] = malloc(1024);
if (ptrs[i] == NULL) {
fprintf(stderr, "Failed to allocate memory\n");
exit(1);
}
}
printf("Memory allocated successfully\n");
printf("Freeing memory...\n");
for (int i = 0; i < 1024; i++) {
free(ptrs[i]);
}
printf("Memory freed successfully\n");
return 0;
}
You know, on a Linux system we can trace the system calls that a program makes using the
stracecommand (e.g.strace ./malloc-demo).
Good point, let's do that!
If we trace what system calls this program actually performed, we find the following:
write(1, "Allocating memory...\n", 21) = 21
brk(0x580a37089000) = 0x580a37089000
brk(0x580a370aa000) = 0x580a370aa000
brk(0x580a370cb000) = 0x580a370cb000
brk(0x580a370ec000) = 0x580a370ec000
brk(0x580a3710d000) = 0x580a3710d000
brk(0x580a3712e000) = 0x580a3712e000
brk(0x580a3714f000) = 0x580a3714f000
write(1, "Memory allocated successfully\n", 30) = 30
write(1, "Freeing memory...\n", 18) = 18
brk(0x580a3706a000) = 0x580a3706a000
write(1, "Memory freed successfully\n", 26) = 26
exit_group(0) = ?
We can see that this code was using the Linux brk() system call to allocate memory. The brk() system call is used to change the location of the program break, which specifies the end of the process's data segment (i.e., the program break is the first location after the end of the uninitialized data segment). The brk() system call is used to adjust the size of the data segment to allocate memory dynamically.
Hey, I never saw
brk()in CS 105.
Well, maybe not, but hopefully you can make sense of the idea that there are system calls for memory management.
And
sbrk()/brk()is one of the simplest ways the kernel offers for allocating memory.
We could instead adjust this break point ourselves. Here's an example of how we could do that:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
// Allocate 1024 chunks, each of 1 KB of memory
void *ptrs[1024];
char *bump_ptr;
printf("Allocating one big chunk...\n");
bump_ptr = sbrk(1024 * 1024);
if (bump_ptr == (void*)-1) {
fprintf(stderr, "Failed to allocate memory\n");
exit(1);
}
printf("Memory allocated successfully\n");
// Also make 1024 smaller chunks, but do it ourselves
for (int i = 0; i < 1024; i++) {
ptrs[i] = bump_ptr;
bump_ptr += 1024;
}
printf("Freeing memory...\n");
if (sbrk(-1024 * 1024) == (void*)-1) {
fprintf(stderr, "Failed to free memory\n");
exit(1);
}
printf("Memory freed successfully\n");
return 0;
}
If we run this code, it makes the following system calls:
write(1, "Allocating one big chunk...\n", 28) = 28
brk(0x5aa74d323000) = 0x5aa74d323000
write(1, "Memory allocated successfully\n", 30) = 30
write(1, "Freeing memory...\n", 18) = 18
brk(0x5aa74d223000) = 0x5aa74d223000
write(1, "Memory freed successfully\n", 26) = 26
exit_group(0) = ?
In this code, we use sbrk() to adjust the location of the program break (which, in Linux, is turned into the even simpler brk() system call).
(In most modern Unix-based code that asks the kernel for memory directly, a more flexible memory-management system call is used, such as mmap(), but as we can see, malloc and free still do use sbrk() on Linux.)
Virtual Memory and Paging
In CS 105, you learned also about virtual memory and paging.
(When logged in, completion status appears here.)