[Linux kernel] memory management - kernel memory partition

Reprint please specify: https://www.cnblogs.com/Ethan-Code/p/16619091.html

kernel memory partition

The virtual memory size in a 32-bit machine is 4GB, of which 0~3GB is used for user space, and 3~4GB is used for kernel space.

The memory space of the kernel is only 1G, and this part of the memory is shared in the process, isolated from the user space, and cannot be accessed by the user space.

The kernel space is divided into three sections on virtual memory: from low to high are:

  • ZONE_DMA(16M)
  • ZONE_NORMAL(16~896M)
  • ZONE_HIGHMEM(896~1024M)

The specific and physical memory mapping of each interval is as follows:

It can be clearly seen from this picture that the virtual memory with virtual address 3G~3G+896M is directly linearly mapped to the physical memory with physical address 0~896M. So the memory mapping on this is very efficient.

The virtual address of 3.896G~4G is called high-end memory, which is divided into three parts: non-continuous memory area, permanent kernel mapping area and fixed mapping area.

ZONE_DMA

ZONE_DMA: 16M linear mapping area (3~3.016G)

The physical pages in this area are dedicated to DMA for I/O devices .

The reasons for the need to manage the physical pages of DMA separately:

  1. DMA uses physical addresses to access memory without going through the MMU
  2. Needs a contiguous buffer

In order to provide a physically contiguous buffer, an area must be specially allocated from the physical address space for DMA.

For example, dma_alloc_coherentthe memory acquired by the function is ZONE_DMA memory, and the consistency is guaranteed.

If you are interested in cache consistency issues, please refer to: https://www.cnblogs.com/Ethan-Code/p/16652513.html

ZONE_NORMAL

ZONE_NORMAL: 880M linear mapping area (3.016~3.896G)

The physical pages in this area can be directly used by the kernel, such as code segments in the kernel program, global variables, and heap memory obtained by kmalloc .

The memory obtained from here is generally continuous, but not too large.

kmalloc applies for direct linear mapping of continuous physical memory. Because direct mapping does not require the establishment of page tables, it is more efficient. The disadvantage is that it can only allocate small memory.

ZONE_HIGHMEM

ZONE_HIGHMEM: 128M high-end memory (3.896~4G)

The area is more complex and can be subdivided into three parts:

1. Non-contiguous memory area

The non-contiguous memory area can also be called a dynamic mapping area, or a vmalloc partition.

It can map discontinuous page frames on physical memory to continuous kernel virtual addresses, and is mainly used for large-capacity memory allocation .

The main advantage of allocating memory in this way is that it avoids external fragmentation, but the disadvantage is that the kernel page table must be disturbed, and the access speed is slower than that of a continuously allocated physical page frame.

The function vmalloc maps physical memory pages through this part of the virtual address. It is allocated by page, which is completely different from the direct mapping of kmalloc.

Question: The non-contiguous memory area is only 128M, how does vmalloc allocate large memory?

When the kernel wants to access a physical address higher than 896M, you can call ** vmalloc** to take (borrow) a part of the virtual address space from 0xF8000000(3G) ~ 0xFFFFFFFF(4G) to establish a mapping with the physical memory page frame, that is, to fill the kernel PTE page surface. After the access is completed, it is released by the kernel for other processes to access.
Use this 128M virtual space to establish temporary address mapping (borrow other free virtual addresses to access physical memory) to complete access to all physical memory higher than 896M. Realized the use of limited address space to access all physical memory.

For example, the kernel wants to access a section of physical memory starting from 2G with a size of 1MB (such as 0×80000000 ~ 0x800FFFFF). Before accessing, find a 1MB free virtual address space (such as 0xF8700000 ~ 0xF87FFFFF), and use this 1MB logical address space to map to the memory in the physical address space 0×80000000 ~ 0x800FFFFF.

2. Permanent kernel mapping area

If the page corresponding to the high-end memory is obtained through alloc_page(), how to find a linear space for it?

The kernel reserves a linear space for this purpose, from PKMAP_BASE to FIXADDR_START, for mapping high-end memory.

On the 2.6 kernel, this address range is between 4G-8M and 4G-4M. This space uses the same page directory table as other spaces. For the kernel, it is swapper_pg_dir. For ordinary processes, it is pointed to by the CR3 register.

Normally, this space is 4M in size, so only one page table is needed, and the kernel looks for this page table through pkmap_page_table.

Through kmap(), a page can be mapped to this space.

Since this space is 4M in size, up to 1024 pages can be mapped at the same time. Therefore, for unused pages, they should be released from this space in time (that is, the mapping relationship is released). Through kunmap(), the linear address corresponding to a page can be released from this space.

3. Fixed mapping area

The kernel reserves some linear space between FIXADDR_START and FIXADDR_TOP for special needs. This space is called the fixed mapping space .

In this space, a part is used for temporary mapping of high-end memory.

This space has the following characteristics:

  1. One space per CPU
  2. The space occupied by each CPU is divided into multiple small spaces, each small space is 1 page, and each small space is used for a purpose, and these purposes are defined in km_type in kmap_types.h.

When performing a temporary mapping, you need to specify the purpose of the mapping. According to the purpose of the mapping, you can find the corresponding small space, and then use the address of this space as the mapping address. This means that a temporary mapping causes previous mappings to be overwritten.

kmap_atomic()Temporary mappings can be achieved via .

The specific kernel memory distribution is as follows:

The difference between kmalloc and vmalloc

  • kmalloc allocates continuous small memory, which is allocated in the linear mapping area of ​​the kernel (in the 896M of linear mapping), and the allocated memory is based on slab.

  • vmalloc allocates memory that is contiguous on virtual addresses and not contiguous on physical addresses. Each allocation needs to establish a PTE kernel page table, which has a large overhead.

The principle of vmalloc is very ingenious. From the above we know that the non-contiguous memory area of ​​the kernel is very small and only occupies a part of the 128M high-end memory. So how does it realize the allocation and access of large memory? In fact, its implementation is divided into two steps:

  1. Call get_vm_area()the function to apply for a valid virtual memory address.
  2. Call vmalloc_area_pages()function to map virtual memory address to physical memory address.

Both kmalloc() and vmalloc() are functions provided in the kernel code to other subsystems to allocate memory.

In general, kmalloc() is called in the driver to allocate memory for the data structure.

Only hardware devices need memory with continuous physical addresses, because hardware devices often exist outside the MMU and do not understand virtual addresses at all. Therefore, for performance considerations, kmalloc() is generally used in the kernel

And vmalloc() is used to allocate data structures for the active swap area, allocate buffers for some I/O drivers, or allocate space for modules.

Only use vmalloc() when you need to get a large block of memory, for example, when the module is dynamically loaded into the kernel, load the module on the memory allocated by vmalloc().


Reference: https://www.cnblogs.com/hongzhunzhun/p/4533960.html
https://www.lxlinux.net/1652.html
https://blog.csdn.net/hardworkba/article/details/10365135
https ://blog.csdn.net/chen1540524015/article/details/73719410
The difference between kmalloc and vmalloc
The principle and implementation of vmalloc

Guess you like

Origin blog.csdn.net/weixin_45636061/article/details/127184799