转自:http://www.bkjia.com/Linuxjc/443717.html

内存映射结构:

1.32位地址线寻址4G的内存空间,其中0-3G为用户程序所独有,3G-4G为内核占有。

2.struct page:整个物理内存在初始化时,每个4kb页面生成一个对应的struct page结构,这个page结构就独一无二的代表这个物理内存页面,并存放在mem_map全局数组中。

3.段式映射:首先根据代码段选择子cs为索引,以GDT值为起始地址的段描述表中选择出对应的段描述符,随后根据段描述符的基址,本段长度,权限信息等进行校验,校验成功后。cs:offset中的32位偏移量直接与本段基址相累加,得出最终访问地址。

0-3G与mem_map的映射方式:
因linux中采用的段式映射为flat模式,所以从逻辑地址到线性地址没有变化。从段式出来进入页式,每个用户进程都独自拥有一个页目录表(pdt),运行时存放于CR3。 
CR3(页目录) + 前10位 =>  页面表基址 + 中10位 => 页表项 + 后12位 => 物理页面地址

3G-4G与mem_map的映射方式:
分为三种类型:低端内存/普通内存/高端内存。
低端内存:3G-3G+16M 用于DMA        __pa线性映射
普通内存:3G+16M-3G+896M          __pa线性映射 (若物理内存<896M,则分界点就在3G+实际内存)
高端内存:3G+896-4G               采用动态的分配方式

4.高端内存(假设3G+896为高端内存起址)
作用:访问到1G以外的物理内存空间。
线性地址共分为三段:vmalloc段/kmap段/kmap_atomic段(针对与不同的内存分配方式)

从内存分配函数的结构来看主要分为下面几个部分:
a.伙伴算法(最原始的面向页的分配方式)
alloc_pages 接口:
    struct page * alloc_page(unsigned int gfp_mask)——分配一页物理内存并返回该页物理内存的page结构指针。
    struct page * alloc_pages(unsigned int gfp_mask, unsigned int order)——分配 个连续的物理页并返回分配的第一个物理页的page结构指针。
    <释放函数:__free_page(s)>
    
    内核中定义:#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)   
    最终都是调用 __alloc_pages.
    其中MAX_ORDER 11,及最大分配到到页面个数为2^10(即4M)。
    分配页后还不能直接用,需要得到该页对应的虚拟地址:
    void *page_address(struct page *page);
    低端内存的映射方式:__va((unsigned long)(page  -  mem_map)  <<  12)
    高端内存到映射方式:struct page_address_map分配一个动态结构来管理高端内存。(内核是访问不到vma的3G以下的虚拟地址的) 具体映射由kmap / kmap_atomic执行。
    
get_free_page接口:(alloc_pages接口两步的替代函数)
    unsigned long get_free_page(unsigned int gfp_mask)
    unsigned long __get_free_page(unsigned int gfp_mask)
    Unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int order)
    <释放函数:free_page>
    与alloc_page(s)系列最大的区别是无法申请高端内存,因为它返回到是一个线性地址,而高端内存是需要额外映射才可以访问的。

b.slab高速缓存(反复分配很多同一大小内存)   注:使用较少
    kmem_cache_t* xx_cache;
    创建: xx_cache = kmem_cache_create("name", sizeof(struct xx), SLAB_HWCACHE_ALIGN, NULL, NULL);
    分配: kmem_cache_alloc(xx_cache, GFP_KERNEL);
    释放: kmem_cache_free(xx_cache, addr);
  内存池
      mempool 不使用。
 
c.kmalloc(最常用的分配接口)         注:必须小于128KB
    GFP_ATOMIC 不休眠,用于中断处理等情况
    GFP_KERNEL 会休眠,一般状况使用此标记
    GFP_USER   会休眠
    __GFP_DMA  分配DMA内存
    kmalloc/kfree
    
d.vmalloc/vfree
    vmalloc采用高端内存预留的虚拟空间来收集内存碎片引起的不连续的物理内存页,是用于非连续物理内存分配。
当kmalloc分配不到内存且无物理内存连续的需求时,可以使用。(优先从高端内存中查找)
    
e.ioremap()/iounmap()
  ioremap()的作用是把device寄存器和内存的物理地址区域映射到内核虚拟区域,返回值为内核的虚拟地址。使用的线性地址区间也在vmmlloc段
注:
vmalloc()与 alloc_pages(_GFP_HIGHMEM)+kmap();前者不连续,后者只能映射一个高端内存页面
__get_free_pages与alloc_pages(NORMAL)+page_address(); 两者完全等同
内核地址通过 __va/__pa进行中低内存的直接映射
高端内存采用kmap/kmap_atomic的方式来映射

个人总结如下:
a.在<128kB的一般内存分配时,使用kmalloc
    允许睡眠:GFP_KERNEL
    不允许睡眠:GFP_ATOMIC
b.在>128kB的内存分配时,使用get_free_pages,获取成片页面,直接返回虚拟地址(<4M)(或alloc_pages + page_address)
c.b失败,
    如果要求分配高端内存:alloc_pages(_GFP_HIGHMEM)+kmap(仅能映射一个页面)
    如果不要求内存连续: 则使用vmalloc进行分配逻辑连续的大块页面.(不建议)/分配速度较慢,访问速率较慢。
d.频繁创建和销毁很多较大数据结构,使用slab.
e.高端内存映射:
    允许睡眠:kmap              (永久映射)
    不允许睡眠:kmap_atomic      (临时映射)会覆盖以前到映射(不建议)

linux内存分配方法总结【转】的更多相关文章

  1. 深入理解Linux内存分配

    深入理解Linux内存分配 为了写一个用户层程序,你也许会声明一个全局变量,这个全局变量可能是一个int类型也可能是一个数组,而声明之后你有可能会先初始化它,也有可能放在之后用到它的时候再初始化.除此 ...

  2. C语言内存分配方法。

    当C程序运行在操作系统上时,操作系统会给每一个程序分配一定的栈空间. 堆为所有程序共有的,需要时需要申请访问. 一.栈 局部变量.函数一般在栈空间中. 运行时自动分配&自动回收:栈是自动管理的 ...

  3. linux内存分配

    在linux的内存分配机制中,优先使用物理内存,当物理内存还有空闲时(还够用),不会释放其占用内存,就算占用内存的程序已经被关闭了,该程序所占用的内存用来做缓存使用,对于开启过的程序.或是读取刚存取过 ...

  4. Linux内存分配----SLAB

    动态内存管理 内存管理的目标是提供一种方法,为实现各种目的而在各个用户之间实现内存共享.内存管理方法应该实现以下两个功能: 最小化管理内存所需的时间 最大化用于一般应用的可用内存(最小化管理开销) 内 ...

  5. 内存分配方法 kmalloc()、vmalloc()、__get_free_pages()

    Copyright: 该文章版权由潘云登所有.可在非商业目的下任意传播和复制. 对于商业目的下对本文的任何行为需经作者同意. kmalloc #include <linux/slab.h> ...

  6. linux内存分配机制

    这几天在观察apache使用内存情况,所以特意了解了下linux的内存机制,发现一篇写得还不错.转来看看. 一般来说在ps aux中看到的rss就是进程所占用的物理内存.但是如果将所有程序的rss加起 ...

  7. Linux 内存使用方法详细解析

    我是一名程序员,那么我在这里以一个程序员的角度来讲解Linux内存的使用. 一提到内存管理,我们头脑中闪出的两个概念,就是虚拟内存,与物理内存.这两个概念主要来自于linux内核的支持. Linux在 ...

  8. Linux内存使用方法详细解析

    我是一名程序员,那么我在这里以一个程序员的角度来讲解Linux内存的使用. 一提到内存管理,我们头脑中闪出的两个概念,就是虚拟内存,与物理内存.这两个概念主要来自于linux内核的支持. Linux在 ...

  9. 从malloc中窥探Linux内存分配策略

        malloc函数是C/C++中常用内存分配库函数,本篇文章将以Linux平台上的malloc为剖析对象,深入了解分配一块内存的旅程. malloc入门      使用malloc,需要包含头文 ...

随机推荐

  1. 【前端学习笔记04】JavaScript数据通信Ajax方法封装

    //Ajax 方法封装 //设置数据格式 function setData(data){ if(!data){ return ''; } else{ var arr = []; for(k in da ...

  2. python的N个小功能(找到符合要求的图片,重命名,改格式,缩放,进行随机分配)

    ########################################################################## 循环读取该目录下所有子目录和子文件 ####### ...

  3. 从原理上搞定编码(二)-- Web编码

    周末宅在家里睡完觉就吃饭,吃完饭接着睡觉,这日子过的实在是没劲啊.明明还有计划中的事情没有做, 为什么就是不想去做呢,这样的生活持续下去,必然会成为一个彻头彻尾的loser.上一篇写的 初识编码 ,这 ...

  4. openstack的网络配置

    首先在浏览器输入咱们的控制节点的ip地址登陆horizon,也就是dashboard控制页面 输入好用户名与密码,这时输入的用户名与密码会与我们的老大哥keystone进行认证.确认你输入的这个用户有 ...

  5. BZOJ4887 Tjoi2017可乐(动态规划+矩阵快速幂)

    设f[i][j]为第i天到达j号城市的方案数,转移显然,答案即为每天在每个点的方案数之和.矩乘一发即可. #include<iostream> #include<cstdio> ...

  6. Simpsons’ Hidden Talents HDU - 2594(拓展kmp)

    Sample Input clinton homer riemann marjorie Sample Output 0 rie 3 看输出才题意...拓展kmp特征很明显嘛....注意开始就匹配到尾的 ...

  7. [JSOI2009]电子字典 hash

    题面:洛谷 题解: 做法....非常暴力. 因为要求的编辑距离最多只有1,所以我们直接枚举对那个位置(字符)进行操作,进行什么样的操作,加入/修改/删除哪个字符,然后暴力枚举hash判断即可, #in ...

  8. Java高级应用之泛型与反射20170627

    /*************************************************************************************************** ...

  9. C++ STL 一般总结(转载)

    注:原博地址:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/22/2603525.html 以下内容来源网上 经过整合而成 一.一般介绍 STL ...

  10. 省选模拟赛 LYK loves graph(graph)

    题目描述 LYK喜欢花花绿绿的图片,有一天它得到了一张彩色图片,这张图片可以看做是一张n*m的网格图,每个格子都有一种颜色去染着,我们用-1至n*m-1来表示一个格子的颜色.特别地,-1代表这个颜色是 ...