Table of contents
First, the hierarchical relationship of memory management

Second, the process image
Programs and Processes:
A program is an executable file stored on the disk. When the program is run, the system will load the executable file into the memory and run it.
A running program is called a process. A program can be executed multiple times at the same time to form multiple processes. Each process is independent of each other and managed by the operating system.
reason.
What is a process image:
The layout of the process in the memory space is the process image, from low address to high address:

What data is stored in each memory segment:
code area
(text)
:
It stores binary instructions, literal constants, and
const
modified original
data
The variable of the memory segment, the permission is
r--
or
r-x
.
data area
(data)
:
It stores the initialized global variables and static variables.
BSS
Area:
It stores uninitialized global and static local variables. Once the process loads all bytes of this memory segment, it will be cleaned up as
0
, so the default values for global and static variables are
0
.
heap area
(heap)
:
Will be dynamically allocated, extending from low address to high address, in
C
The language needs to call
malloc
Series functions are managed, while
malloc
The bottom layer calls the system's
API
interface
(brk/sbrk/mmap/munmap)
.
stack area
(stack)
:
It stores non-static local variables and block variables, including function parameters and return values, extending from high addresses to low addresses.
There is a gap between the heap area and the stack area. On the one hand, space is reserved for the growth of the heap and the stack. At the same time, the shared library and shared memory are also located in the
this.
Command line parameters and environment variables table:
It stores command line arguments and environment variables.
#include <stdio.h> #include <stdlib.h> const int const_global = 0; // constant global variable int init_global = 0; // Initialize global variables int uninit_global; // uninitialized global variable int main(int argc, char *argv[]) { const static int const_static = 0; // constant static variable static int init_static = 0; // initialize static variables static int uninit_static; // static variable not initialized }
3. Virtual memory
The first thing we need to understand is that the operating system cannot directly allocate physical memory to the process.
It is directly assigned to the process, which will face serious security problems. The process can operate on the pointer according to the memory address obtained by itself.
Thereby accessing the memory space of other processes to destroy, and even affect the security of the operating system, so the virtual memory space introduced by the design of the operating system
concept of survival.
What is virtual memory:
Virtual memory is used by the operating system kernel to manage the process address space (
process address space management
)and
A well-designed logical memory space concept.
exist
32
Under the system, the operating system stipulates that each process has
4G
virtual memory, but this
4G
The memory space cannot be used directly, nor
It is the pie that the operating system draws for the process. When the process really needs to use memory to store data, the operating system will use part of the virtual memory.
Mapping with physical memory, the mapped virtual memory can be used normally.
const int const_local = 0; // constant local variable int prev_local; // former local variable int next_local; // back local variable int *prev_heap = malloc(sizeof(int)); // front heap variable int *next_heap = malloc(sizeof(int)); // back heap variable const char *literal = "literal"; // literal constant extern char **environ; // environment variable printf("---- Command Line Arguments and Environment Variables ---- <high>\n"); printf(" Environment variables:%p\n", environ); printf(" Command line arguments:%p\n", argv); printf("-------------- stack ------------\n"); printf(" Constant local variables:%p\n", &const_local); printf(" Front local variable:%p\n", &prev_local); printf(" After local variables:%p\n", &next_local); printf("-------------- heap ------------\n"); printf(" Post heap variables:%p\n", next_heap); printf(" Front heap variable:%p\n", prev_heap); printf("------------- BSS ------------\n"); printf(" Uninitialized global variables:%p\n", &uninit_global); printf(" Static variables are not initialized:%p\n", &uninit_static); printf("------------ data ------------\n"); printf(" Initialize static variables:%p\n", &init_static); printf(" Initialize global variables:%p\n", &init_global); printf("------------ code ------------\n"); printf(" Constant static variables:%p\n", &const_static); printf(" Literal constants:%p\n", literal); printf(" Constant global variables:%p\n", &const_global); printf(" function:%p\n", main); printf("------------------------------ <Low>\n"); printf("Check/proc/%u/maps,according to<Enter>quit...", getpid()); getchar(); return 0; }
User space and kernel space:
per process
4G
Virtual memory is divided into two parts according to different users.
User space:
[0x00000000,0xC0000000)
part, with
3GB
The size, after being mapped by the operating system, is used in the application, the program
It cannot directly access the code and data in the kernel space, but can enter the kernel state through system calls and indirectly interact with the system kernel.
Kernel space:
[0xC0000000,0xFFFFFFFF]
part, with
1GB
The size can only be used by the operating system. It stores the relevant data required by the operating system to serve the process or interact with the process. The kernel space is managed by the operating system kernel and will not change with process switching.
The user space corresponds to a process. Once the process is switched, the user space changes accordingly, and the memory space of each process is completely independent. Swapping virtual memory addresses between different processes is pointless
What are the benefits of using virtual memory for processes:
1
, the operating system allocates a
4G
Virtual memory space, which can isolate processes to avoid mutual influence between processes,
destroy
2
, operating system
4G
The virtual memory is divided into user mode and kernel mode, which can isolate the process from the operating system and avoid the process
impact on the operating system.
3
, The operating system can also map the files on the hard disk with the virtual memory. When the physical memory is not enough, you can also use the hard disk instead.
instead, albeit at a slower pace.
Note: A program is a virus if it can affect and destroy other processes and the operating system.
Fourth, memory mapping
Automatic mapping:
When the program is executed, the operating system will automatically map it after it is loaded into the memory to form a process.
text
,
data
,
bss
,
statck
, command line parameter table, environment variable table for memory mapping.
Manual mapping:
First use in a program
malloc
When requesting memory, at this time
malloc
There is no heap memory to allocate in hand, that is, there is no mapped memory to allocate, malloc
Will apply to the operating system for mapping
33
page virtual memory, which
33
page memory
malloc
Managed, and then apply for memory to malloc,
malloc
will map from this
33
page memory allocated to the caller, while
malloc
The underlying function calls the operating system API
The interface completes the mapping operation.
If the program wants to use a small amount of heap memory, it cannot be achieved
33
page, then use
malloc
Applying for memory will cause memory waste, you can directly adjust
operating system
API
interface for more precise memory mapping.
int main(int argc, char *argv[]) { int num = 123456; printf("%lu",(unsigned long)&num); getchar(); } // Program B int main(int argc, char *argv[]) { int* ptr = NULL; scanf("%lu",(unsigned long*)&num); printf("%d",*ptr); }
Five, Linux system memory management API
POSIX-compliant memory management API:
#include <unistd.h> // brk and sbrk maintain a pointer p internally, pointing to the next location address of the last byte of the current heap memory. void *sbrk(intptr_t increment); Function: Adjust according to parameters p s position(p+/-increment),Virtual memory can be both mapped and unmapped. Return value: before adjustment p s position. int brk(void *addr); Function: Modify according to pointer parameters p s position(Bundle p Set as addr). Return value: return 0 on success, return on failure-1. // Note: Both brk and sbrk can allocate/release memory independently, but they are generally used together, sbrk is allocated by the user, and brk is used for release. // Note: brk and sbrk can only be used to map virtual memory, and cannot achieve refined management.
Example: Calculate
100
arrive
100000
All prime numbers are stored in memory.
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <unistd.h> #include <math.h> bool is_prime(int num) { int end = sqrt(num); for(int i=2; i<=end; i++) { if(0 == num % i) return false; } return true; } int main(int argc,const char* argv[]) { int* base = sbrk(0); for(int i=100; i<10000; i++) { if(is_prime(i)) { int* p = sbrk(4); *p = i; } } int *p = base, *end = sbrk(0); while(p < end) { printf("%d ",*p++); } printf("\n"); brk(base); return 0; }
Memory management of Linux system:
#include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
Function:
1
, The virtual memory of the user space is mapped with the physical memory.
2
, The virtual memory of the user space is mapped to the file.
addr
: The first address of the virtual memory you want to map, if it is
NULL
The operating system automatically calculates.
length
: the number of bytes to map,
prot
: mapped memory permissions
PROT_EXEC
execute permission
PROT_READ
read permission
PROT_WRITE
write permission
PROT_NONE
No permission
flags
:
MAP_SHARED
Shared mapping, the contents of the mapping are visible to other processes, and writing to the shared area is equivalent to outputting to a file.
MAP_PRIVATE
Private mapping, the contents of the mapping are invisible to other processes
MAP_DENYWRITE
Deny other file write operations
MAP_ANON
Maps memory instead of files
fd
:
file descriptor, similar to file pointer
FILE
offset
:
Offset to use when mapping files
Return value: the virtual memory address after the mapping is successful, if it fails, the return value is
0xffffffff
int
munmap
(
void *
addr
,
size_t
length
);
Function: Unmap
addr
: The first address of the mapped memory
length
: number of bytes of memory
Return value: return successfully
0
, return on failure
-
1
.
//
Note: The memory map of the system is in units of pages
(4096byte)
#include <stdio.h> #include <sys/mman.h> int main(int argc,const char* argv[]) { FILE* fp = fopen("test.txt","r+"); if(NULL == fp) { perror("fopen"); return -1; } int fd = fileno(fp); char* str = mmap(NULL, 100, PROT_WRITE|PROT_READ, MAP_SHARED|MAP_FILE, fd, 0); printf("%s\n",str); sprintf(str,"Hello World\n"); munmap(str,100); fclose(fp); return 0; }