是不是我错了,本想这个函数会如网上所说将进行非连续内存管理的初始化,但是对于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的更多相关文章

  1. 内存管理 初始化(八) 至kswapd_init

    至此,内存初始化部分已看完,遗留问题: 1.对于unicore或者mips的页表建立都很清楚,但是对于ARM我不清楚: 初始化部分涉及的页表映射建立,我都以unicore架构为准,ARM的页表映射从原 ...

  2. linux内存管理初始化

    内存管理子系统是linux内核最核心最重要的一部分,内核的其他部分都需要在内存管理子系统的基础上运行.而对其初始化是了解整个内存管理子系统的基础.对相关数据结构的初始化是从全局启动例程start_ke ...

  3. 伙伴系统之避免碎片--Linux内存管理(十六)

    1 前景提要 1.1 碎片化问题 分页与分段 页是信息的物理单位, 分页是为了实现非连续分配, 以便解决内存碎片问题, 或者说分页是由于系统管理的需要. 段是信息的逻辑单位,它含有一组意义相对完整的信 ...

  4. 内存管理 初始化(五)kmem_cache_init 初始化slab分配器(上)

    看了下kmem_cache_init,涉及到不同MIGRATE间的buddy system的迁移,kmem_cache的构建,slab分配器头的构建.buddy system的伙伴拆分. 对于SMP系 ...

  5. 内存管理初始化源码4:add_active_range

    我们在阅读源码时,函数功能可以分为两类:1. bootmem.c 2. page_alloc.c. 1. bootmem.c是关于bootmem allocator的,上篇文章已经简述过. 2. pa ...

  6. 内存管理初始化源码3:bootmem

    start_kernel ——> setup_arch ——> arch_mem_init ——> bootmem_init ——> init_bootmem_node: 此时 ...

  7. 内存管理初始化源码2:setup_arch

    PFN相关宏说明: /* kernel/include/linux/pfn.h */ PFN : Page Frame Number(物理页帧) /* * PFN_ALIGN:返回地址x所在那一页帧的 ...

  8. 内存管理初始化源码1:setup_arch

    源码声明:基于Linux kernel 3.08 1. 在kernel/arch/mips/kernel/head.S中会做一些特定硬件相关的初始化,然后会调用内核启动函数:start_kernel: ...

  9. 内存管理 初始化(二)bootmem位图分配器建立 及 使用

    本地的笔记有点长,先把bootmem位图分配器的建立 及  使用过程做下梳理. 都是代码,上面做了标注.开始的汇编部分省略了(涉及的内容不多,除了swapper_pg_dir的分配). 该记录不会再添 ...

随机推荐

  1. [转]JSP页面的动态包含和静态包含示例及介绍

    原文地址:http://www.jb51.net/article/53659.htm 一.静态包含 本文介绍JSP静态包含语句,即使用JSP的include指令来完成的包含操作.JSP中,有两种包含其 ...

  2. [Linux]阿里云免费试用体验(在阿里云的ubuntu上部署个人服务)

    作为一个IT界的人,一般都希望有一个独立的博客,或者一部独立的机器.所以我一直在找机会,拥有一台自己可以独立控制的机器,自己想干嘛干嘛.当然这在虚拟机或者自己的PC上面也可以实现,但是这跟一台一直开着 ...

  3. Git克隆部分文件

    克隆部分文件html, body {overflow-x: initial !important;}.CodeMirror { height: auto; } .CodeMirror-scroll { ...

  4. C语言 · 求arccos值

    算法提高 7-2求arccos值   时间限制:10.0s   内存限制:256.0MB      问题描述 利用标准库中的cos(x)和fabs(x)函数实现arccos(x)函数,x取值范围是[- ...

  5. 头文件中ifndef/define/endif的作用以及#pragma once使用

    例如:要编写头文件test.h 在头文件开头写上两行: #ifndef _TEST_H #define _TEST_H//一般是文件名的大写 ············ ············ 头文件 ...

  6. SpringMVC REST 风格静态资源访问配置

    1 在web.xml中使用默认servlet处理静态资源,缺点是如果静态资源过多,则配置量会比较大,一旦有遗漏,则会造成资源无法正常显示或404错误. <!-- 静态资源访问控制 --> ...

  7. 设备接口体应用container_of的思考

    结构体应用container_of,可参考 container_of

  8. swing自定义border

    public class MyBorder extends AbstractBorder { private static final long serialVersionUID = 1L; priv ...

  9. EF5.x Code First 一对多关联条件查询,Contains,Any,All

    背景 通过多个部门id获取所有用户,部门和用户是多对多. 已知部门id,获取该部门包括该部门下的所有子部门的所有用户. 关系如下: public class Entity:IEntity { publ ...

  10. elasticsearch 服务安全配置

    elasticsearch安装与使用(5)-- search guard安装与配置   一.安装search guard插件必须要安装两部分: ①search-guard-xx ②search-gua ...