内存管理 初始化(六)vmalloc_init 及 ioremap
是不是我错了,本想这个函数会如网上所说将进行非连续内存管理的初始化,但是对于2.6.34的ARM架构而言,该函数实际完成的业务非常少。
内存管理的初始化读到此处,我感觉原有的认识存在很大缺陷:
(1)内核空间的下限是3G吗?永久映射的PKMAP_BASE已在3G下;
(2)低端内存是896M吗?2.6.32的omap4430的VMLLOC_END是1G - 128M,VMALLOC_MIN是1G - 128M -128M;
(3)还存在固定映射吗?FIXADDR_SIZE的空间已被FIX_KMAP_BEGIN ~ FIXK_KMAP_END完全占据;
(4)I/O空间在初始化已固定映射至VMALLOC_END到FIXADDR_START之间的一块虚拟空间区域.
(5)用户态不可以执行3G以上空间代码吗?kuser_cmpxchg_check检测的意义;
(6)引入MODULES_END的意义是什么?
对于ARM架构,vmalloc_init中的for循环就没有执行,如有误,望指正.
void vmalloc_init(void)
|-->for_each_possible_cpu(i)
|--{
| struct vmap_block_queue *vbq;
| vbq = &per_cpu(vmap_block_queue, i);
| spin_lock_init(&vbp->lock);
| INIT_LIST_HEAD(&vbq->free);
|--}
|
|--for(tmp = vmlist; tmp; tmp = tmp->next)
|--{
| xxxxxxxx
| 对于2..34的ARM架构而言,vmlist直到此时仍为0;
| 所以该循环不会执行,至于网上的资料大概是针对X86的.
|--}
|
|--vmap_area_pcpu_hole = VMALLOC_END;
| vmap_initialized = true;
如下部分是我后期再看init_arch_irq()中看的,主要是因为我们知道:对于ARM架构, vmalloc_init中的for循环没有执行,那么我们自然会想何时对首次修改vmlist以及如何修改.
init_arch_irq中会执行ioremap函数,以下记录该函数的执行流程.
#define ioremap(cookie, size) \
__arm_ioremap(cookie, size, MT_DEVICE) void *__arm_ioremap(unsigned long phys_addr, size_t size,
unsigned int mtype)
|-->__arm_ioremap_caller(phys_addr, size, mtype, NULL) void *__arm_ioremap_caller(unsigned long phys_addr, size_t size,
unsigned int mtype, void *caller)
|-->unsigned long offset = phys_addr & ~PAGE_MASK;
| 对于SOC,例如sep612,每个IP模块的所占空间都是4K的整数倍,所以
| 一般情况下offset = ;
|
|-->unsigned long pfn = __phys_to_pfn(phys_addr);
|
|-->return __arm_ioremap_pfn_caller(pfn, offset, size, mtype, caller);
void *__arm_ioremap_pfn_caller(unsigned long pfn, unsigned long offset,
size_t size, unsigned int mtype, void *caller)
|-->const struct mem_type *type = get_mem_type(mtype)
| mem_type中存放页表映射属性,及页表的级数
|
|-->size = PAGE_ALIGN(offset + size);
|
|-->struct vm_struct *area = get_vm_area_caller(size, VM_IOREMAP,
| caller);
| 根据size,在VMALLOC_START ~ VMALLOC_END中申请一块size + PAGE_SIZE
| 大小的虚拟空间,由于非连续内存区域的管理还利用了红黑树,因此在获得vm_struct
| 实例的同时,也将申请vmap_area实例,将申请的虚拟空间,纳入红黑树
| vmap_area_root.rb_node的管理.
|
|-->unsigned long addr = (unsigned long)area->addr;
|
|-->remap_area_pages(addr, pfn, size, type);
| 前面讲过,申请的虚拟空间是size + PAGE_SIZE,此处我们看到,
| 映射的物理空间大小是size.
|
|-->flush_cache_vmap(addr, addr+size);
|
|-->return (void *) (offset + addr);
struct vm_struct *get_vm_area_caller(unsigned long size,
unsigned long flags, void *caller)
|-->return __get_vm_area_node(size, , flags, VMALLOC_START,
VMALLOC_END, -, GFP_KERNEL, caller); struct vm_struct *__get_vm_area_node(unsigned long size,
unsigned long align, unsigned long flags,
unsigned long start, unsigned long end,
int node, gfp_t gfp_mask, void *caller)
|-->struct vmap_area *va = NULL;
| struct vm_struct *area = NULL;
|
|-->if(flags & VM_IOREMAP)
|--{
| int bit = fls(size);
| if(bit > IOREMAP_MAX_ORDER) bit = IOREMAP_MAX_ORDER;
| else if(bit < PAGE_SHIFT) bit = PAGE_SHIFT;
| align = << bit;
|--}
| 对于IO 映射部分做了对其修正.
|
|
|-->size = PAGE_ALIGN(size);
|
|-->area = kzalloc_node(sizeof(*area), gfp_mask & GPF_RECLAIM_MASK,
| node);
| 对于非连续内存区,既使用了vmlist这样的链表管理,也使用了vmap_area_root
| 之类的红黑树进行管理,此处即申请需插入到vmlist链表中的vm_struct实例中.
|
|-->size += PAGE_SIZE;
| 为了安全考虑,多申请了一页的虚拟空间(注意只是虚拟空间).
|
|-->va = alloc_vmap_area(size, align, start, end, node, gpf_mask);
| 从虚拟内存start ~ end中申请一块size大小的虚拟空间,起止地址放在
| vmap_area实例中,并将该vmap_area实例插入到以vmap_area_root.rb_node
| 为根的红黑树中.
|
|-->insert_vmalloc_vm(area, va, flags, caller);
| 将vmap_area实例和vm_struct实例关联起来,并将vm_struct实例插入到
| vmlist链表中.
将vmap_area实例和vm_struct实例关联起来,并将vm_struct实例插入到vmlist链表中.
void insert_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va)
|-->struct vm_struct *tmp, **p;
|
|-->vm->flags = flags;
| vm->addr = (void *)va->va_start;
| vm->size = va->va_end - va->va_start;
| vm->caller = caller;
| va->private = vm;
| va->flags |= VM_VM_AREA;
|
|-->for(p = &vmlist; (tmp = *p) != NULL; p = &tmp->next)
|--{
| if(tmp->addr >= vm->addr) break;
|--}
|
|--vm->next = *p;
| *p = vm;
内存管理 初始化(六)vmalloc_init 及 ioremap的更多相关文章
- 内存管理 初始化(八) 至kswapd_init
至此,内存初始化部分已看完,遗留问题: 1.对于unicore或者mips的页表建立都很清楚,但是对于ARM我不清楚: 初始化部分涉及的页表映射建立,我都以unicore架构为准,ARM的页表映射从原 ...
- linux内存管理初始化
内存管理子系统是linux内核最核心最重要的一部分,内核的其他部分都需要在内存管理子系统的基础上运行.而对其初始化是了解整个内存管理子系统的基础.对相关数据结构的初始化是从全局启动例程start_ke ...
- 伙伴系统之避免碎片--Linux内存管理(十六)
1 前景提要 1.1 碎片化问题 分页与分段 页是信息的物理单位, 分页是为了实现非连续分配, 以便解决内存碎片问题, 或者说分页是由于系统管理的需要. 段是信息的逻辑单位,它含有一组意义相对完整的信 ...
- 内存管理 初始化(五)kmem_cache_init 初始化slab分配器(上)
看了下kmem_cache_init,涉及到不同MIGRATE间的buddy system的迁移,kmem_cache的构建,slab分配器头的构建.buddy system的伙伴拆分. 对于SMP系 ...
- 内存管理初始化源码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: ...
- 内存管理 初始化(二)bootmem位图分配器建立 及 使用
本地的笔记有点长,先把bootmem位图分配器的建立 及 使用过程做下梳理. 都是代码,上面做了标注.开始的汇编部分省略了(涉及的内容不多,除了swapper_pg_dir的分配). 该记录不会再添 ...
随机推荐
- Mysql注入绕过姿势
1.内联绕过 2.编码绕过,如URLEncode编码,ASCII,HEX,unicode编码绕过 or 1=1即%6f%72%20%31%3d%31,而Test也可以为CHAR(101)+CHAR(9 ...
- jsp传给java属性,java生成json串,方便以后取出来
前台代码 $.ajax({ url : '<%=basePath%>userorderother/canUpdateCust.do', type : 'POST', data: {'kdc ...
- 为什么说Thunderbird是最好的桌面RSS阅读器
也许现在再讨论RSS阅读器似乎已经过时了,毕竟随着社交网络服务的发展,通过一个带有大众评分能力的社交网络(比如reddit),相比RSS的固定订阅而言,也许你能更快地在你所关心的话题上更快地获得新的资 ...
- mongoDb CPU利用率100%的分析和解决
在公司的项目中,突然出现过一个情况,mongodb 的CPU利用率到达100%,导致服务器这边卡死了,请求了半天无响应,提示请求超时. 因为,当时APP用户可能会在某一个时间段集中的使用,所以,请求量 ...
- ython strip lstrip rstrip使用方法
Python中的strip用于去除字符串的首尾字符,同理,lstrip用于去除左边的字符,rstrip用于去除右边的字符. 这三个函数都可传入一个参数,指定要去除的首尾字符. 需要注意的是,传入的是一 ...
- C# BCC异或校验法
通讯协议中最后一位是校验位 采用BCC(异或校验)法 这个怎么解释? 就是 把16进制的字符串转换成byte[]数据,依次拿出来进行异或一下 然后返回的值和校验位对比下 看看对不对 例如: 23230 ...
- C/C++-标准输入/输出重定向为文件输入/输出
/* Time: 2017-02-22 11:11:15 Describe: C++程序将标准输入/输出重定向为文件输入/输出. */ #include <iostream> #inclu ...
- js 实现遮罩某一部分
借用一下喜马拉雅的效果图,比较一下下面的遮罩层的高度: 我们可以看到它的遮罩层一直都是只遮住的下面.开始想着怎么用CSS实现,几经测试也没弄出来,如果正在看这篇文章的你,知道如何用CSS达 ...
- 微信小程序——引用阿里云字体
阿里图标官网:http://www.iconfont.cn 使用阿里云图标大致的方法就是:选中你的图标——保存至你的项目——下载你的图标项目——在项目中引用字体文件. 具体方法可以参考:引用阿里云矢量 ...
- 安卓程序代写 网上程序代写[原]BluetoothSocket详解
一. BluetoothSocket简介 1. 简介 客户端与服务端 : BluetoothSocket 和 BluetoothServerSocket 类似于Java中的套接字的 Socket 和 ...