linux 内存管理笔记

最近看了一篇论文,觉得里面对linux内存管理的讲解还比较可以,就做了点笔记记录下来。

用户空间:

1.      使用malloc()函数在进程的堆上分配内存。

2.      Malloc()函数其实是调用brk()系统调用分配内存,该函数的作用是以页面大小扩大或缩小堆空间,但分配的时候还是以字节为单位进行分配,所以malloc()函数可以动态地分配内存大小。

物理内存管理:

1.      分页机制(减少了外部碎片)

2.      为了分配连续内存,降低TLB的刷新率,采用“伙伴系统”管理物理内存(页)。

3.      伙伴系统提供的两个分配物理内存的函数:get_free_page()和get_free_pages(),前者只分配单页,后者分配2n物理页。

4.      在linux系统中每一页物理内存用struct page描述,所有的物理页储存在一个全局数组中mem_map[]中,可以通过该数组查找到所有的物理页。

Slab:

1.      其实就是一个提前分配的内存池,里面的内存是重复利用的,避免频繁创建和销毁带来的开销。

2.      建立在伙伴系统之上,可以很好利用硬件缓存提高访问速度。

3.      将伙伴系统提供的物理页分成众多小内存块以供分配,用来满足内核经常发生的对小于一页的小内存分配(减少内部碎片)。

4.      Kmem_cache_alloc()和kmem_cache_free()函数提供对内核专用对象(固定大小、结构体)的内存分配和销毁。

5.      Kmalloc()分配小内存块,内存分配粒度更灵活,可分配32~131072(128K)大小范围的内存;kmalloc()分配的函数分配的空间被称为内核逻辑地址,由于其是连续分配的,而且首地址一定,所以与物理地址的映射只需要减去一个固定的偏移量(PAGE_OFFSET),其对应的页表属于内核页表(swapper_pg_dir),在系统初始化时就已建立。

6.      Slab不仅为上面两种内存分配保留了内存,而且还为DMA准备一部分内存。

内核非连续内存分配(Vmalloc):

1.      将非连续的内存块(页)整合成大块内存,用于分配(彻底消除外部碎片)。

2.      借鉴了用户空间分配的虚拟内存,内存逻辑上是连续的,但实际上物理内存并不一定是连续的;和用户进程相似,内核也有一个名为init_mm的mm_struct结构来描述内核地址空间,其中页表项pdg=swapper_pg_dir包含了系统内核空间的映射关系。

3.      可以分配很大的内存空间,最大可以将近1G(几百M),但需要对内核虚拟地址重新映射,更新内核表,因此分配效率上要抵一些。

比较:

1.      vmalloc()和get_free_page()/kmalloc()分配的内核虚拟内存位于不同的区间。由get_free_page()和kmalloc()分配的连续内存都位于物理映射区域,而由vmalloc()分配的内存为与物理映射区域之后的高地址区。其位置分布如下图所示:

linux 内存管理笔记_第1张图片

2.       kmalloc()和kmem_cache_alloc()的主要区别就是前者可以分配动态大小的内存,而后者不行,只能分配固定大小的内存。如果内存大小(常量)是固定的话,kmalloc()函数是调用kmem_cache_alloc()函数实现,所以基本没区别。如果内存大小是变化的,就只能选kmalloc()了。总体来说,kmem_cache_alloc()分配效率要比kmalloc()高一些。

附1 用户空间和内核空间内存映射原理图

linux 内存管理笔记_第2张图片


 


你可能感兴趣的:(linux 内存管理笔记)