转自:http://blog.csdn.net/myarrow/article/details/8682819

1. First Fit分配器

First Fit分配器是最基本的内存分配器,它使用bitmap而不是空闲块列表来表示内存。在bitmap中,如果page对应位为1,则表示此page已经被分配,为0则表示此page没有被分配。为了分配小于一个page的内存块,First Fit分配器记录了最后被分配的PFN (Page Frame Number)和分配的结束地址在页内的偏移量。随后小的内存分配被Merge到一起并存储到同一页中。

First Fit分配器不会造成严重的内存碎片,但其效率较低,由于内存经常通过线性地址进行search,而First Fit中的小块内存经常在物理内存的开始处,为了分配大块内存而不得不扫描前面大量的内存。

2. Boot Memory分配器

物理内存分配器如何分配内存来初始化其自己呢?

答案是:通过Boot Memory分配器来实现,而Boot Memory分配器则通过最基本的First Fit分配器来实现。

2.1 Boot Map定义

Boot Map通过数据结构bootmem_data来定义,详见<linux/bootmem.h>,其定义如下所示:

  1. typedef struct bootmem_data {
  2. unsigned long node_boot_start; // 描述的物理内存的起始地址
  3. unsigned long node_low_pfn;    // 结束物理地址,即ZONE_NORMAL的结束
  4. void *node_bootmem_map;        // 描述“使用或空闲的位图”的地址
  5. unsigned long last_offset;     // 最后被分配的页内偏移量,即在llast_pos描述的物理页中,
  6. // 从last_offset开始,没有被分配
  7. unsigned long last_pos;        // 最后被分配的页的PFN
  8. } bootmem_data_t;

所有bootmem_data被放于全局变量bdata_list中。

2.2 Boot Memory分配器初始化

每一个CPU架构被要求提供setup_arch函数,它负责获取初始化boot memory分配器的必要参数。不同的CPU架构通过不同的函数来实现,如ARM通过bootmem_init来实现。它负责获取以下参数:

• min_low_pfn: 系统中可获得的最小的PFN,装载kernel image结束之后的第一页,在mm/bootmem.c中定义

• max_low_pfn:低端内存(ZONE_NORMAL)中可获得的最大PFN

• highstart_pfn:高端内存(ZONE_HIGHMEM)的起始PFN

• highend_pfn:高端内存(ZONE_HIGHMEM)的结束PFN

• max_pfn:系统中可获得的最大的PFN, 在mm/bootmem.c中定义

PFN是在物理内存map的偏移量,以page为单位。Kernel可直接访问ZONE_NORMAL,其偏移量为:PAGE_OFFSET。

通过以上5个参数明确了可用物理内存之后,调用init_bootmem->init_bootmem_core来初始化contig_page_data。它主要完成以下两件事:

1) 将把与此node对应pgdat_data_t插入到pgdat_list中

2) 初始化bootmem_data_t的中参数,并分配表示页分配状态的bitmap,其大小为: (end_pfn-start_pfn+7)/8

bitmap的物理地址为:bootmem_data_t->node_boot_start

bitmap的虚拟地直为:bootmem_data_t->node_bootmem_map

2.3 分配内存

• reserve_bootmem:用于预留物理页面。但用于通用的内存分配是低率的,它主要用于各种驱动(如:Video Codec)预留内存。

常用的内存分配函数如下(in UMA架构,我们常的ARM架构为UMA架构):

• alloc_bootmem

• alloc_bootmem_low

• alloc_bootmem_pages

• alloc_bootmem_low_pages

其调用关系如下图所示:

2.3.1  __alloc_bootmem

__alloc_bootmem() 需要以下参数:

     • pgdat

用于分配内存块的节点,在UMA架构中,它被忽略,因为它总是为:contig_page_data

     • size

指定请求分配的内存大小,以字节为单位

     • align

请求以多少字节对齐,地于小块内存分配,一般以SMP_CACHE_BYTES对齐,如在X86上,与L1硬件cache对齐

     • goal

偏好的分配内存的起始地址,

2.3.2 __alloc_bootmem_core

它从goal指定的地址开始,线性地扫描内存,以寻找可以满足内存分配要求的内存块。它的另外一项功能是决定是否需要把新分配的内存块与以前已经分配的内存块merge到一起。

分配内存常用函数定义如下:

  1. #ifdef CONFIG_NO_BOOTMEM
  2. /* We are using top down, so it is safe to use 0 here */
  3. #define BOOTMEM_LOW_LIMIT 0
  4. #else
  5. #define BOOTMEM_LOW_LIMIT __pa(MAX_DMA_ADDRESS)
  6. #endif
  7. #define alloc_bootmem(x) \
  8. __alloc_bootmem(x, SMP_CACHE_BYTES, BOOTMEM_LOW_LIMIT)
  9. #define alloc_bootmem_align(x, align) \
  10. __alloc_bootmem(x, align, BOOTMEM_LOW_LIMIT)
  11. #define alloc_bootmem_nopanic(x) \
  12. __alloc_bootmem_nopanic(x, SMP_CACHE_BYTES, BOOTMEM_LOW_LIMIT)
  13. #define alloc_bootmem_pages(x) \
  14. __alloc_bootmem(x, PAGE_SIZE, BOOTMEM_LOW_LIMIT)
  15. #define alloc_bootmem_pages_nopanic(x) \
  16. __alloc_bootmem_nopanic(x, PAGE_SIZE, BOOTMEM_LOW_LIMIT)
  17. #define alloc_bootmem_node(pgdat, x) \
  18. __alloc_bootmem_node(pgdat, x, SMP_CACHE_BYTES, BOOTMEM_LOW_LIMIT)
  19. #define alloc_bootmem_node_nopanic(pgdat, x) \
  20. __alloc_bootmem_node_nopanic(pgdat, x, SMP_CACHE_BYTES, BOOTMEM_LOW_LIMIT)
  21. #define alloc_bootmem_pages_node(pgdat, x) \
  22. __alloc_bootmem_node(pgdat, x, PAGE_SIZE, BOOTMEM_LOW_LIMIT)
  23. #define alloc_bootmem_pages_node_nopanic(pgdat, x) \
  24. __alloc_bootmem_node_nopanic(pgdat, x, PAGE_SIZE, BOOTMEM_LOW_LIMIT)
  25. #define alloc_bootmem_low(x) \
  26. __alloc_bootmem_low(x, SMP_CACHE_BYTES, 0)
  27. #define alloc_bootmem_low_pages(x) \
  28. __alloc_bootmem_low(x, PAGE_SIZE, 0)
  29. #define alloc_bootmem_low_pages_node(pgdat, x) \
  30. __alloc_bootmem_low_node(pgdat, x, PAGE_SIZE, 0)

2.4 释放内存

调用free_bootmem来释放内存。

    1. void __init free_bootmem(unsigned long addr, unsigned long size)
    2. {
    3. unsigned long start, end;
    4. kmemleak_free_part(__va(addr), size);
    5. start = PFN_UP(addr);
    6. end = PFN_DOWN(addr + size);
    7. mark_bootmem(start, end, 0, 0);
    8. }

Linux内存管理--物理内存分配【转】的更多相关文章

  1. Linux内存管理 (4)分配物理页面

    专题:Linux内存管理专题 关键词:分配掩码.伙伴系统.水位(watermark).空闲伙伴块合并. 我们知道Linux内存管理是以页为单位进行的,对内存的管理是通过伙伴系统进行. 从Linux内存 ...

  2. Linux内存管理 (1)物理内存初始化

    专题:Linux内存管理专题 关键词:用户内核空间划分.Node/Zone/Page.memblock.PGD/PUD/PMD/PTE.lowmem/highmem.ZONE_DMA/ZONE_NOR ...

  3. 浅谈Linux内存管理机制

    经常遇到一些刚接触Linux的新手会问内存占用怎么那么多?在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这 ...

  4. linux内存管理

    一.Linux 进程在内存中的数据结构 一个可执行程序在存储(没有调入内存)时分为代码段,数据段,未初始化数据段三部分:    1) 代码段:存放CPU执行的机器指令.通常代码区是共享的,即其它执行程 ...

  5. Linux内存管理原理

    本文以32位机器为准,串讲一些内存管理的知识点. 1. 虚拟地址.物理地址.逻辑地址.线性地址 虚拟地址又叫线性地址.linux没有采用分段机制,所以逻辑地址和虚拟地址(线性地址)(在用户态,内核态逻 ...

  6. 了解linux内存管理机制(转)

    今天了解了下linux内存管理机制,在这里记录下,原文在这里http://ixdba.blog.51cto.com/2895551/541355 根据自己的理解画了张图: 下面是转载的内容: 一 物理 ...

  7. Linux内存管理原理【转】

    转自:http://www.cnblogs.com/zhaoyl/p/3695517.html 本文以32位机器为准,串讲一些内存管理的知识点. 1. 虚拟地址.物理地址.逻辑地址.线性地址 虚拟地址 ...

  8. Windows内存管理和linux内存管理

    windows内存管理 windows 内存管理方式主要分为:页式管理,段式管理,段页式管理. 页式管理的基本原理是将各进程的虚拟空间划分为若干个长度相等的页:页式管理把内存空间按照页的大小划分成片或 ...

  9. linux 内存管理——内核的shmall 和shmmax 参数

    内核的 shmall 和 shmmax 参数 SHMMAX= 配置了最大的内存segment的大小 ------>这个设置的比SGA_MAX_SIZE大比较好. SHMMIN= 最小的内存seg ...

随机推荐

  1. 自学Aruba5.3.3-Aruba安全认证-有PEFNG 许可证环境的认证配置Captive-Portal

    点击返回:自学Aruba之路 自学Aruba5.3.3-Aruba安全认证-有PEFNG 许可证环境的认证配置Captive-Portal 1. Captive-Portal认证配置前言 1.1 新建 ...

  2. 架构师成长之路2.3-PXE+Kickstart无人值守大量部署Linux

    点击返回架构师成长之路 架构师成长之路2.3-PXE+Kickstart无人值守大量部署Linux 所谓的无人值守,就是自动应答,当安装过程中需要人机交互提供某些选项的答案时(如如何分区),自动应答文 ...

  3. 【BZOJ1998】[HNOI2010]物品调度(并查集,模拟)

    [BZOJ1998][HNOI2010]物品调度(并查集,模拟) 题面 BZOJ,为啥这题都是权限题啊? 洛谷 题解 先不管\(0\)位置是个空,把它也看成一个箱子.那么最终的答案显然和置换循环节的个 ...

  4. sql server 小技巧(1) 导入csv数据到sql server

    1. 右击 DataBaseName,选择 Tasks->Import Data 2. 选择数据源: Flat File Source , 选择一个csv文件 Advance: 选择所有的列,改 ...

  5. Windows下修改Tomcat黑窗口标题

    在Tomcat的bin目录下,新建文件setenv.bat. 在文件内输入: set TITLE=MYTomcat-%date% %time%[%cd%] 可以把MYTomcat修改为自己定义的名字. ...

  6. 服务器内存占用不断的增加 & 任务管理器(PF使用率)不断的增加:关注句柄数

    最近一二个月以来,我发现服务器的内存占用正按着每天60M的速度增加. 一台windows 2003的服务器(2G内存),刚刚启起时占用内存:600M左右. 运行20天后,内存占用(PF使用):1.8G ...

  7. Java + 腾讯邮箱 SSL加密问题 重要通知

    原来的jdk8版本如果不替换jce就会在发邮件的过程中报错,而此次使用的jdk1.8.0_131,并没有出现问题,也就是说,如果你使用的版本是 就不用考虑发邮件因为加密算法而导致的错误了

  8. Mac下Vim编辑快捷键小结(移动光标)

    Mac下Vim编辑快捷键小结(移动光标) 1.移动到行尾"$",移动到行首"0"(数字),移动到行首第一个字符处"^" 2.移动到段首&qu ...

  9. eclipse中中文注释乱码怎么解决

    作项目一般都是用UTF-8编码的,eclipse的默认编码是GBK,你在菜单栏Window里,选Preferences选项,第一项General里的Workspace,选定后右面有个Text file ...

  10. (母函数 Catalan数 大数乘法 大数除法) Train Problem II hdu1023

    Train Problem II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...