Linux内核学习6:内存管理(2)

1:虚拟内存技术

Linux内存管理采用虚拟内存技术,使得每个进程都有独立的进程地址空间,该大小有3G。

问题描述一:Linux系统为什么采用虚拟内存技术?

每个进程有独立的进程地址空间,达到3G,用户看到和接触到的都是虚拟内存。无法看到实际的物理地址。利用这中虚拟内存技术不仅可以保护到操作系统,更重要的是用户可以使用到比实际物理内存更大的地址空间。

Linux把4G的虚拟内存划分为两个部分——用户空间(进程的)和内核空间。用户进程通常情况下不能访问内核空间,只有通过系统调用方可访问内核空间。

用户空间对应着进程,因此每次进程切换时,用户空间都是在变化的。(页式转换的信息发生改变)

2:如何在Linux内核中分配内存空间?

分配给进程的,获得的不是物理内存,而是虚拟地址。实际物理内存只有当进程真的去访问新获得的新的虚拟地址时,才会有”请页机制“产生缺页异常。从而进入分配实际页框的程序。该异常是虚拟内存机制赖以存在的基本保证——它会告诉内核去为进程分配物理页,并建立对应的页表,之后虚拟地址才实实在在的映射到了物理地址。

在应用程序中使用malloc函数进行动态的内存分配。在Linux中通常使用kmalloc来动态分配内存。

具体的机制流程图如下图所示:

1)Linux内存页管理

Linux内核管理物理内存是通过分页机制实现的。它将整个内存划分为4k大小的页,作为分配和回收的基本单位。

利用分页管理有助于灵活分配内存地址,因为分配时不必要求必须有大块的连续内存,系统可以凑出所需要的内存供给进程使用。虽然如此,但是实际上系统使用内存还是倾向于分配连续的内存块。因为分配连续的内存时,页表不需要更改。因此降低了TLB的刷新率。

2)slab管理器技术

slab技术简介:先从物理页分配一部分出来,划分为一个个的64字节,128字节等的链表。每个链表都有一定的内存。但动态分配内存时,如果是56字节的,则拿出一个64字节的链表供其使用。这样的小内存片段被看做对象,当被使用完后,并不直接释放,而是被缓存到”存储池“里,留给下次使用。这样就避免了频繁创建与销毁对象所带来的额外负载

3)kmalloc

一般来说内核程序中对小于一页的小块内存的请求会通过slab分配器提供的接口kmlloc来完成(虽然它可分配32~131072byte的内存)。从内核内存分配的角度来讲kmalloc可被看做是get_free_page(s)的一个有效补充,内存分配颗粒更灵活了。

函数原型:

<span style="font-family:KaiTi_GB2312;font-size:18px;">#include <linux/slab.h>void *kmalloc(size_t size,int flags);</span>

参数说明:flags有很多种。这里也不详细介绍。

4)按页分配与伙伴关系

伙伴关系:内核分配物理内存为了尽量减少不连续情况,采用”伙伴“关系管理空闲页框。因此空闲页面分配时需要遵循伙伴关系,最小单位只能是2的幂倍页面大小。内核中分配空闲页框基本函数是:get_free_page/get_free_pages;它们或是分配单页或是分配指定的页框

按页分配:如果需要分配大块的内存,那使用面向页的分配技术会更好。具体的函数有以下几种:

get_zero_page(unsigned int flags);//返回指向新页面的指针,并将页面清0
_get_free_page(unsigned int flags);//和get_free_page类似,但不清0
_get_free_pages(unsigned int flags,unsigned int order);//分配若干个连续页面,返回指向该内存区域的指针,但也不清0

当用完这些页以后,可以使用如下函数来释放它们:

void free_page(unsigned long addr);void free_pages(unsigned long addr,unsigned long order);

流过泪的眼睛更明亮,滴过血的心灵更坚强!

Linux内核学习6:内存管理(2)

相关文章:

你感兴趣的文章:

标签云: