内存管理 初始化(三)before mm_init()
看到了mm_init(),期间将从bootmem迁移到伙伴系统,slab分配器也会建立。
在分析mm_init()之前,把setup_arch(&command_line)之后的函数分析了以下,详见注释。
start_kernel()
|---->page_address_init()
| 考虑支持高端内存
| 业务:初始化page_address_pool链表;
| 将page_address_maps数组元素按索引降序插入
| page_address_pool链表;
| 初始化page_address_htable数组.
|
|---->setup_arch(&command_line);
|
|---->setup_per_cpu_areas();
| 为per-CPU变量分配空间
|
|---->build_all_zonelist()
| 为系统中的zone建立后备zone的列表.
| 2.6.34中的建立过程与《深入Linux内核架构》中p_134~p_135的图不符
| (即使是UMA也不同),书中讲述是每个zone都有自己的zonelist,
| 2.6.34中对于UMA,所有zone的后备列表都在
| pglist_data->node_zonelists[]中;
|
| 期间也对per-CPU变量boot_pageset做了初始化.
|
|---->page_alloc_init()
|---->hotcpu_notifier(page_alloc_cpu_notifier, );
| 不考虑热插拔CPU
|
|---->pidhash_init()
| 详见下文.
| 根据低端内存页数和散列度,分配hash空间,并赋予pid_hash
|
|---->vfs_caches_init_early()
|---->dcache_init_early()
| dentry_hashtable空间,d_hash_shift, h_hash_mask赋值;
| 同pidhash_init();
| 区别:
| 散列度变化了( - PAGE_SHIFT);
| 传入alloc_large_system_hash的最后参数值为0;
|
|---->inode_init_early()
| inode_hashtable空间,i_hash_shift, i_hash_mask赋值;
| 同pidhash_init();
| 区别:
| 散列度变化了( - PAGE_SHIFT);
| 传入alloc_large_system_hash的最后参数值为0;
|
void pidhash_init(void)
|---->pid_hash = alloc_large_system_hash("PID", sizeof(*pid_hash),
| , , HASH_EARLY|HASH_SMALL, &pidhash_shift, NULL, );
| 根据nr_kernel_pages(低端内存的页数),分配哈希数组,以及各个哈希
| 数组元素下的哈希链表的空间,原理如下:
| number = nr_kernel_pages;
| number >= ( - PAGE_SHIFT) 根据散列度获得数组元素个数
| number = roundup_pow_of_two(number);
| pidhash_shift = max{x | **x <= number}
| size = number * sizeof(*pid_hash);
| 使用位图分配器分配size空间,将返回值付给pid_hash;
|
|---->pidhash_size = << pidhash_shift;
|
|---->for(i = ; i < pidhash_size; i++)
| INIT_HLIST_HEAD(&pid_hash[i]);
void build_all_zonelists(void)
|---->set_zonelist_order()
|---->current_zonelist_order = ZONELIST_ORDER_ZONE;
|
|---->__build_all_zonelists(NULL);
| Memory不支持热插拔, 为每个zone建立后备的zone,
| 每个zone及自己后备的zone,形成zonelist
|
|---->vm_total_pages = nr_free_pagecache_pages();
| 业务:获得所有zone中的present_pages总和.
|
|---->page_group_by_mobility_disabled = ;
| 对于代码中的判断条件一般不会成立,因为页数会最够多(内存较大)
static int __build_all_zonelists(void *dummy)
|---->pg_data_t *pgdat = NULL;
| pgdat = &contig_page_data;(单node)
|
|---->build_zonelists(pgdat);
| 为每个zone建立后备zone的列表
|
|---->build_zonelist_cache(pgdat);
|---->pdat->node_zonelists[].zlcache_ptr = NULL;
| UMA体系结构
|
|---->for_each_possible_cpu(cpu)
| setup_pageset(&per_cpu(boot_pageset, cpu), );
|详见下文
void build_zonelists(pg_data *pgdat)
|---->struct zonelist *zonelist = NULL;
| enum zone_type j;
| zonelist = &pgdat->node_zonelists[];
|
|---->j = build_zonelists_node(pddat, zonelist, , MAX_NR_ZONES - );
| 为pgdat->node_zones[]建立后备的zone,node_zones[]后备的zone
| 存储在node_zonelist[]内,对于node_zone[]的后备zone,其后备的zone
| 链表如下(只考虑UMA体系,而且不考虑ZONE_DMA):
| node_zonelist[]._zonerefs[].zone = &node_zones[];
| node_zonelist[]._zonerefs[].zone_idx = ;
| node_zonelist[]._zonerefs[].zone = &node_zones[];
| node_zonelist[]._zonerefs[].zone_idx = ;
| node_zonelist[]._zonerefs[].zone = &node_zones[];
| node_zonelist[]._zonerefs[].zone_idx = ;
|
| zonelist->_zonerefs[].zone = NULL;
| zonelist->_zonerefs[].zone_idx = ;
void setup_pageset(struct per_cpu_pageset *p, unsigned long batch)
|---->memset(p, , sizeof(*p));
|
|---->struct per_cpu_pages *pcp = NULL;
| pcp = &p->pcp;
| pcp->count = ;
| pcp->high = * batch;
| pcp->batch = max(1UL, * batch);
|
|---->for(migratetype = ;
| migratetype < MIGRATE_PCPTYPES;
| migratetype++)
|---->INIT_LIST_HEAD(&pcp->lists[migratetype]);
unsigned int nr_free_pagecache_pages(void)
|-->return nr_free_zone_pages(gfp_zone(GFP_HIGHUSER_MOVABLE));
对于UMA,且不考虑ZONE_DMA,参数为2
|-->参数offset = ;
| struct zoneref *z =NULL;
| struct zone *zone = NULL;
| unsigned int sum = ;
| struct zonelist *zonelist =
| node_zonelist(numa_node_id(), GFP_KERNEL)
| 对于UMA,zonelist =
| (&contig_page_data)->node_zonelists;
|
|-->for_each_zone_zonelist(zone, z, zonelist, offset)
| offset的作用在于遍历zonelist下的_zonerefs数组元数中,
| zone_idx <= offset的zone;
| 因此当offset为0时,遍历的结果相当于
| zone = &pglist_data->node_zones[]
|
| unsigned long size = zone->present_pages;
| 获得该zone跨越的页数.
|
| unsigned long high = high_wmark_pages(zone);
| if(size > high) sum += size - high;
| (high暂时为0,因为zone->watermark[WMARK_HIGH] = )
|
|-->return sum;
内存管理 初始化(三)before mm_init()的更多相关文章
- 内存管理 初始化(八) 至kswapd_init
至此,内存初始化部分已看完,遗留问题: 1.对于unicore或者mips的页表建立都很清楚,但是对于ARM我不清楚: 初始化部分涉及的页表映射建立,我都以unicore架构为准,ARM的页表映射从原 ...
- 垃圾回收GC:.Net自己主动内存管理 上(三)终结器
垃圾回收GC:.Net自己主动内存管理 上(三)终结器 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己主 ...
- 内存管理 初始化(五)kmem_cache_init 初始化slab分配器(上)
看了下kmem_cache_init,涉及到不同MIGRATE间的buddy system的迁移,kmem_cache的构建,slab分配器头的构建.buddy system的伙伴拆分. 对于SMP系 ...
- linux内存管理初始化
内存管理子系统是linux内核最核心最重要的一部分,内核的其他部分都需要在内存管理子系统的基础上运行.而对其初始化是了解整个内存管理子系统的基础.对相关数据结构的初始化是从全局启动例程start_ke ...
- 内存管理 初始化(六)vmalloc_init 及 ioremap
是不是我错了,本想这个函数会如网上所说将进行非连续内存管理的初始化,但是对于2.6.34的ARM架构而言,该函数实际完成的业务非常少. 内存管理的初始化读到此处,我感觉原有的认识存在很大缺陷: (1) ...
- 内存管理初始化源码4:add_active_range
我们在阅读源码时,函数功能可以分为两类:1. bootmem.c 2. page_alloc.c. 1. bootmem.c是关于bootmem allocator的,上篇文章已经简述过. 2. pa ...
- 内存管理初始化源码3:bootmem
start_kernel ——> setup_arch ——> arch_mem_init ——> bootmem_init ——> init_bootmem_node: 此时 ...
- 内存管理初始化源码2:setup_arch
PFN相关宏说明: /* kernel/include/linux/pfn.h */ PFN : Page Frame Number(物理页帧) /* * PFN_ALIGN:返回地址x所在那一页帧的 ...
- 内存管理初始化源码1:setup_arch
源码声明:基于Linux kernel 3.08 1. 在kernel/arch/mips/kernel/head.S中会做一些特定硬件相关的初始化,然后会调用内核启动函数:start_kernel: ...
随机推荐
- 基于jQuery环形图标菜单旋转切换特效
分享一款基于jQuery环形图标旋转切换特效.这是一款鼠标点击图标菜单圆形顺时针或者逆时针旋转切换代码.效果图如下: 在线预览 源码下载 实现的代码. js代码: /* 图片地址可以是相对路径或绝 ...
- CentOS重置Mysql密码
1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库. 因为在重新设置MySQL的root密码的期间,MySQL数据库完全出于没有密码保护的 状态下,其他的用户也可以任意地登录 ...
- JAVA是否可以作脚本语言呢
答:是可以的. 只是叫另一个名字-beanshell.印象里她好像还是第一款jvm语言.应该挺多年没更新了. 我之所以知道它,是当年折腾jEdit这款编辑器较多,它的内置脚本引擎使用的就是beansh ...
- git——添加远程库
添加远程库 阅读: 406682 现在的情景是,你已经在本地创建了一个Git仓库后,又想在GitHub创建一个Git仓库,并且让这两个仓库进行远程同步,这样,GitHub上的仓库既可以作为备份,又可以 ...
- layui栅格布局问题
在使用layer.open弹出到窗口中,使用布局一直不起作用. 开始到写法如下, 目的是一行分成左右两块,比例为8:4等分. <div class="layui-fluid" ...
- 切换tab页
//切换Tab页 $('#tt').tabs({ border:false, onSelect:function(title){ ...
- C++ vector清空元素的三种方法
#include <iostream> #include <vector> using namespace std; //STL vector的几种清空容器(删除)办法 voi ...
- windows下 删除指定文件夹里面一周前的所有文件和文件夹的bat
forfiles /p "指定文件夹路径" /m * /s /d -7 /c "cmd /c if @isdir==TRUE (rd /q @path) else del ...
- 权限控制-JS判断是否有权限进行操作跳转页面需要加target
妈蛋的,这问题花了我20分钟,我用来搜索代码花了18分钟,我写代码有个差生的习惯,就是抄,啥东西想做,就上网搜别人杂写,拿下来照抄改一下即可 啧啧,妈蛋的,整个一页,没有我能用到的信息,那些博客内容一 ...
- 省市区三级联动[JSON+Jquery]
<!DOCTYPE html><head> <title>省市区三级联动[JSON+Jquery]</title> <script src=&qu ...