Hierarchical relationship of memory management, process image, virtual memory, memory mapping, Linux system memory management API

Table of contents

First, the hierarchical relationship of memory management

Second, the process image

3. Virtual memory

Fourth, memory mapping

Five, Linux system memory management API

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

Tags: data structure jvm Algorithm C linked list

Posted by st0rmer on Sun, 04 Sep 2022 11:02:20 +0930