mem_init()
原本由bootmem管理的内存在mem_init函数中交由伙伴系统管理。
1.free_unused_memmap_node
相邻的membank间可能存在空洞,但在bootmem阶段这些空洞页也分配了page结构体。该函数的作用是找到这些page结构体所占用的内存并且释放掉。
static void __init free_unused_memmap_node(int node, struct meminfo *mi)
-->unsigned long bank_start; //前一个membank的结束地址
-->unsigned long prev_bank_end ;//后一个membank的起始地址
-->free_memmap(node, prev_bank_end, bank_start);
-->struct page *start_pg = pfn_to_page(prev_bank_end);
-->struct page *end_pg = pfn_to_page(bank_start);
-->unsigned long pg = PAGE_ALIGN(__pa(start_pg));
-->unsigned long pgend = __pa(end_pg) & PAGE_MASK;
-->free_bootmem_node(NODE_DATA(node), pg, pgend - pg);
2.移交bootmem分配剩余的空闲页到伙伴系统
该函数返回的是返回给伙伴系统的空闲页数。
unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
{
register_page_bootmem_info_node(pgdat);
return free_all_bootmem_core(pgdat->bdata);
}
空闲页保存在全局变量totalram_pages中
/*mm/page_alloc.c*/
unsigned long totalram_pages __read_mostly;
totalram_pages += free_all_bootmem_node(pgdat);
2.1该函数的核心是free_all_bootmem_core(pgdat->bdata)
static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
-->__free_pages_bootmem(pfn_to_page(start), order);
-->释放掉bdata->node_bootmem_map所占用的内存,彻底废弃bootmem分配器
释放页到伙伴系统底层调用的两个函数是
void __free_pages(struct page *page, unsigned int order)
#define __free_page(page) __free_pages((page), 0)
可以看到,最终调用的还是__free_pages函数
void __free_pages(struct page *page, unsigned int order)
{
if (put_page_testzero(page)) {
if (order == )
free_hot_page(page);
else
__free_pages_ok(page, order);
}
}
free_hot_page流程如下
free_hot_page(page);
-->free_hot_cold_page(page, );
-->struct zone *zone = page_zone(page);
-->struct per_cpu_pages *pcp = &zone_pcp(zone, get_cpu())->pcp;
-->if (cold)
list_add_tail(&page->lru, &pcp->list);/*冷页插入队列末尾*/
else
list_add(&page->lru, &pcp->list);/*热页插入队列首*/
-->pcp->count++;
-->if (pcp->count >= pcp->high)
-->free_pages_bulk(zone, pcp->batch, &pcp->list, );
-->从队列末尾开始删除pcp->batch个页
-->__free_one_page(page, zone, order);/*把删除的页释放到伙伴系统*/
__free_pages_ok流程如下:
static void __free_pages_ok(struct page *page, unsigned int order)
-->free_one_page(page_zone(page), page, order);
-->__free_one_page(page, zone, order);
可以看出,最终调用相同的底层函数__free_one_page,这个函数的实现可以说是伙伴系统的精髓。
这里注意空闲页加入伙伴系统后要做如下的设置。
set_page_order(page, order);
-->set_page_private(page, order);/*设置page->private*/
-->__SetPageBuddy(page);/*设置page->flags*/
list_add(&page->lru,&zone->free_area[order].free_list[migratetype]);
zone->free_area[order].nr_free++;
mem_init()的更多相关文章
- 内存管理 初始化(四)mem_init bootmem 迁移至伙伴系统
mm_init中执行mem_init,将原通过bootmem分配器管理的低端内存 及 通过meminfo得知的高端内存释放到伙伴系统中,最后bootmem位图本身占用的低端内存物理页也被释放进伙伴系 ...
- MMU工作原理
MMU的工作原理就是把虚拟地址转换成物理地址. 虚拟地址:由编译器和连接器在定位程序时分配. 物理地址:用来访问实际的主存硬件模块. 使用虚拟存储器的系统都使用一种称为分页(paging).虚拟地址空 ...
- MIT 6.828 JOS学习笔记17. Lab 3.1 Part A User Environments
Introduction 在这个实验中,我们将实现操作系统的一些基本功能,来实现用户环境下的进程的正常运行.你将会加强JOS内核的功能,为它增添一些重要的数据结构,用来记录用户进程环境的一些信息:创建 ...
- MIT 6.828 JOS学习笔记16. Lab 2.2
Part 3 Kernel Address Space JOS把32位线性地址虚拟空间划分成两个部分.其中用户环境(进程运行环境)通常占据低地址的那部分,叫用户地址空间.而操作系统内核总是占据高地址的 ...
- MIT 6.828 JOS学习笔记15. Lab 2.1
Lab 2: Memory Management lab2中多出来的几个文件: inc/memlayout.h kern/pmap.c kern/pmap.h kern/kclock.h kern/k ...
- Linux内存管理之bootmem分配器
为什么要使用bootmem分配器,内存管理不是有buddy系统和slab分配器吗?由于在系统初始化的时候需要执行一些内存管理,内存分配的任务,这个时候buddy系统,slab分配器等并没有被初始化好, ...
- Linux0.11内核--内存管理之1.初始化
[版权所有,转载请注明出处.出处:http://www.cnblogs.com/joey-hua/p/5597705.html ] Linux内核因为使用了内存分页机制,所以相对来说好理解些.因为内存 ...
- (三)内存 SDRAM 驱动实验 (杨铸 130 页)(勉强能懂个大概)
SDRAM 芯片讲解: 地址: 行地址 (A0-A12) 列地址 (A0-A8) 片选信号(BA0 BA1)(L-BANK)(因为SDRAM有 4片) 两片SDRAM 连线唯一区别在 UDQM ...
- Linux启动过程详述
http://www.ibm.com/developerworks/cn/linux/kernel/startup/index.html Linux启动第1步:引导内核 Linux启动第2步:内核部分 ...
随机推荐
- ASP.NET MVC缓存
根据缓存的位置不同,可以区分为: ①客户端缓存(缓存在用户的客户端,例如浏览器中) ②服务器缓存(缓存在服务器中,可以缓存在内存中,也可以缓存在文件里,并且还可以进一步地区分为本地缓存和分布式缓存两种 ...
- JavaScript获取样式值的几种方法学习总结
本人经过整理总结出以下获取样式值的方法,如有错误请各位大佬指正. 有四种方法:style,currentStyle,getComputedStyle,rules 与 cssRules方法. 1. st ...
- orbbec astra ros
install instruction: https://www.ncnynl.com/archives/201703/1444.html problem: [ERROR] [1481169521.4 ...
- 永洪BI——国内领军的一站式大数据分析平台
平台: CentOS 类型: 虚拟机镜像 软件包: jdk-7.79-linux yonghongbi.sh basic software big data business intelligence ...
- C++编写双向链表
创建双向链表类,该类有默认构造函数.类的拷贝函数.类的.实现链表添加数据.升序排序.查找链表中某个节点及删除链表中某个节点的操作 代码实现: #include<iostream> #inc ...
- org.hibernate.HibernateException: Unable to get the defa
今天整合SSH框架时出现了这个问题,以前一直没注意,在网上找了一下解决方案,找到了问题的解决方法,特记录如下: 1.原因:在中,javax.persistence.validation.mode默认情 ...
- 梦织未来Windows驱动编程 第06课 驱动对磁盘文件的操作
代码部分: 实现一个文件C:\\text.txt,并读取写入内容到文件,然后将文件设置为只读,并隐藏文件.代码如下: //MyCreateFile.c //2016.07.22 #include &l ...
- pat乙级1049
浮点型乘整型和整型乘浮点型结果不同,不知为什么. double sum = 0.0; ; i < n; i++) { cin >> a[i]; sum += a[i] * (i + ...
- WCF的问题
使用service调用WCF的时候,有时候会出现 其他信息: HTTP 无法注册 URL 进程不具有此命名空间的访问权限 这样的问题,这时候就需要进行如下尝试: 1,VS的管理权限使用管理员的权限. ...
- Objective-C 引用计数原理
http://www.cocoachina.com/ios/20160112/14933.html 引用计数如何存储 有些对象如果支持使用 TaggedPointer,苹果会直接将其指针值作为引用计数 ...