[Reprint] five minutes to get to know you have not completely understand the Linux memory management

Five minutes to get to know you have not completely understand the Linux memory management

Most of the servers are now running on top of Linux, so, as a programmer need to simply look at how the system works. For memory part you need to know:

  1. Address Mapping
  2. Memory management approach
  3. Abnormal missing page

First look at some basic knowledge in the process of view, memory is divided into two parts of the kernel mode and user mode, classic proportions as follows:

Usually by a system call from user mode to kernel mode, interrupts to achieve. User-mode memory is divided into different areas for different purposes:

Of course, the kernel mode is not used indiscriminately, therefore, divided as follows:

Here's take a closer look at how the memory is managed.

address

In the address mapping process inside the Linux logical address -> linear address -> physical address, the physical address of the simplest: a digital signal transmitted in the address bus, and linear and logical addresses is represented by a conversion rule, linear address rules are as follows:

This part is completed by the MMU, which have covered the main registers CR0, CR3. Machine instructions that appear in a logical address, the logical address of the following rules:

In Linux logical address is equal to the linear address that is compatible with Inter in order to make things very complicated, Linux simplifies the way lazy.

Memory management approach

In the system boot time will be to probe the memory size and circumstances, pending the establishment of complex structures, need a simple way to manage memory, which is bootmem, is simply a bitmap, but which also has some optimization ideas .

bootmem again how optimization, efficiency is not high, after all, is going to traverse the time to allocate memory, buddy system just to solve this problem: to preserve some power of free memory fragment size 2 inside, if you want to assign 3page, go after taking a list 4page inside, allocate the remaining three one back, memory release process happens to be a reverse process. FIG represented by a:

0,4,5,6,7 are being used can see, then, when 1 is released, they will merge it?

static inline unsigned long __find_buddy_index(unsigned long page_idx, unsigned int order) { return page_idx ^ (1 << order);// 更新最高位,0~1互换 }

从上面这段代码中可以看到,0、1是buddy,2、3是buddy,虽然1、2相邻,但他们不是。内存碎片是系统运行的大敌,伙伴系统机制可以在一定程度上防止碎片~~另外,我们可以通过cat /proc/buddyinfo获取到各order中的空闲的页面数。

伙伴系统每次分配内存都是以页(4KB)为单位的,但系统运行的时候使用的绝大部分的数据结构都是很小的,为一个小对象分配4KB显然是不划算了。Linux中使用slab来解决小对象的分配:

在运行时,slab向buddy“批发”一些内存,加工切块以后“散卖”出去。随着大规模多处理器系统和NUMA系统的广泛应用,slab终于暴露出不足:

  1. 复杂的队列管理
  2. 管理数据和队列存储开销较大
  3. 长时间运行partial队列可能会非常长
  4. 对NUMA支持非常复杂

为了解决这些高手们开发了slub:改造page结构来削减slab管理结构的开销、每个CPU都有一个本地活动的slab(kmem_cache_cpu)等。对于小型的嵌入式系统存在一个slab模拟层slob,在这种系统中它更有优势。

小内存的问题算是解决了,但还有一个大内存的问题:用伙伴系统分配10 x 4KB的数据时,会去16 x 4KB的空闲列表里面去找(这样得到的物理内存是连续的),但很有可能系统里面有内存,但是伙伴系统分配不出来,因为他们被分割成小的片段。那么,vmalloc就是要用这些碎片来拼凑出一个大内存,相当于收集一些“边角料”,组装成一个成品后“出售”:

之前的内存都是直接映射的,第一次感觉到页式管理的存在:D 另外对于高端内存,提供了kmap方法为page分配一个线性地址。

进程由不同长度的段组成:代码段、动态库的代码、全局变量和动态产生数据的堆、栈等,在Linux中为每个进程管理了一套虚拟地址空间:

在我们写代码malloc完以后,并没有马上占用那么大的物理内存,而仅仅是维护上面的虚拟地址空间而已,只有在真正需要的时候才分配物理内存,这就是COW(COPY-ON-WRITE:写时复制)技术,而物理分配的过程就是最复杂的缺页异常处理环节了,下面来看!

缺页异常

在实际需要某个虚拟内存区域的数据之前,和物理内存之间的映射关系不会建立。如果进程访问的虚拟地址空间部分尚未与页帧关联,处理器自动引发一个缺页异常。在内核处理缺页异常时可以拿到的信息如下:

  1. cr2:访问到线性地址
  2. err_code:异常发生时由控制单元压入栈中,表示发生异常的原因
  3. regs:发生异常时寄存器的值

处理的流程如下:

发生缺页异常的时候,可能因为不常使用而被swap到磁盘上了,swap相关的命令如下:

如果内存是mmap映射到内存中的,那么在读、写对应内存的时候也会产生缺页异常。

来源:WsztRush 链接:http://wsztrush.github.io/%E7%BC%96%E7%A8%8B%E6%8A%80%E6%9C%AF/2015/05/13/Linux-Memory.html

原文链接:http://wsztrush.github.io/%E7%BC%96%E7%A8%8B%E6%8A%80%E6%9C%AF/2015/05/13/Linux-Memory.html

编辑于 2019-07-12

Guess you like

Origin www.cnblogs.com/jinanxiaolaohu/p/11646553.html