内存管理 初始化(六)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的分配). 该记录不会再添 ...
随机推荐
- Delphi中的三目运算函数有哪些?(XE10.2+WIN764)
相关资料:https://www.cnblogs.com/rogge7/p/6078903.html 问题现象:在做一个判断时突然想到了C++的三目运算,就在想Delphi中一共有几个? 问题处理: ...
- 基于jquery hover图片遮罩层滑动
分享一款基于jquery hover图片遮罩层滑动.这是一款仿腾讯课堂的鼠标悬停经过图片遮罩透明层滑动效果.效果图如下: 在线预览 源码下载 实现的代码. html代码: <div clas ...
- 自己动手写Android框架-数据库框架
大家在工作中基本上都有使用到数据库框架 关系型:ORMLite,GreenDao 对象型:DB4O,Perst 这些数据库用起来都非常的简单,对于我们Android上来说这些数据库足够我们使用了,但是 ...
- 如何在线程中获取spring 管理的bean
转载自:https://my.oschina.net/skyline520/blog/181158?fromerr=GjtR6Wec spring xml中定义 <!--spring 工具类-- ...
- Android Retrofit2 数据解析
在弄数据解析这块,浪费了很长的时间,最开始一直觉得传过来用对象接收的,类型是json,往那个方式去想了.搞了很久. 后来看了别人写的才发觉,真是很简单,感谢 https://www.jianshu.c ...
- git的版本回退探索
简介 今天改完代码匆忙提交,上线发现有问题,那怎么办?废话,赶紧回滚,那怎么回滚,开始用git reset [--soft | --mixed | --hard 命令,但这命令真的能达到我预期的效果吗 ...
- php 验证所传参数为必填的时候的验证逻辑
此段代码摘自lumen框架: xx/vendor/illuminate/validation/Validator.php /** * Validate that a required attribut ...
- 调整Intellij IDEA内存
最近IDEA真是卡的要死,下面
- JVM相关命题的博客整理及总结
JVM垃圾回收基础介绍 http://www.jianshu.com/p/57457a351b8a 减少JVM中逃逸对象的使用 http://www.importnew.com/23150.html ...
- UEFI Protocol
MEM_INFO_PROTOCOL MEM_INFO_PROTOCOL; EFI_LOADED_IMAGE_PROTOCOL EFI_DEVICE_PATH_PROTOCOL EFI_DRIVER_B ...