初始化非连续内存区

5.8.3 初始化非连续内存区

回到mm_init()函数,继续走,下一个函数pgtable_cache_init (),不知道咋的,是个空函数,也许是保留着以后开发吧。最后一个函数是vmalloc_init(),来自mm/vmalloc.c

 

1088void __init vmalloc_init(void)

1089{

1090        struct vmap_area *va;

1091        struct vm_struct *tmp;

1092        int i;

1093

1094        for_each_possible_cpu(i) {

1095                struct vmap_block_queue *vbq;

1096

1097                vbq = &per_cpu(vmap_block_queue, i);

1098                spin_lock_init(&vbq->lock);

1099                INIT_LIST_HEAD(&vbq->free);

1100        }

1101

1102        /* Import existing vmlist entries. */

1103        for (tmp = vmlist; tmp; tmp = tmp->next) {

1104                va = kzalloc(sizeof(struct vmap_area), GFP_NOWAIT);

1105                va->flags = tmp->flags | VM_VM_AREA;

1106                va->va_start = (unsigned long)tmp->addr;

1107                va->va_end = va->va_start + tmp->size;

1108                __insert_vmap_area(va);

1109        }

1110

1111        vmap_area_pcpu_hole = VMALLOC_END;

1112

1113        vmap_initialized = true;

1114}

 

1090行,vmap_area结构,线性区描述符,就是以前的vm_area_struct结构,它的字段如下所示:

 

struct vmap_area {

       unsigned long va_start;

       unsigned long va_end;

       unsigned long flags;

       struct rb_node rb_node;        /* address sorted rbtree */

       struct list_head list;        /* address sorted list */

       struct list_head purge_list;     /* "lazy purge" list */

       void *private;

       struct rcu_head rcu_head;

};

 

内核内存管理初始化至此,已经接近尾声了,回忆一下:

 

1)内存区的开始部分包含的是对前896MB RAM 进行映射的线性地址。直接映射的物理内存末尾所对应的线性地址保存在high_memory全局变量中。当物理内存小于896MB,则线性地址0xc0000000以后的896MB与其一一对应;当物理内存大于896MB而小于4GB时,只直接映射前896MB的地址到0xc0000000以后的线性空间,然后把线性空间的其他部分与896MB4GB物理空间映射起来,称为动态重映射,这是本博的重点;当物理内存大于4GB,则需要考虑PAE的情况,其他的东东没什么区别,我们不做过多的回忆了。

 

2)内核的页表由内核页全局目录变量swapper_pg_dir维护;pagetable_init()建立内核页表项。

 

3)内存区的结尾部分包含的是固定映射的线性地址,主要用于存放一些常量线性地址,具体查看“高端内存映射 ”博文。

 

4)从PKMAP_BASE 开始,我们查找用于高端内存页框的永久内核映射的线性地址,具体查看“高端内存映射 ”博文。

 

5)其余的线性地址可以用于非连续内存区。在物理内存映射的末尾与第一个内存区之间插入一个大小为8MB(宏VMALLOC_OFFSET)的安全区,目的是为了“捕获”对内存的越界访问。出于同样的理由,插入其他4KB 大小的安全区来隔离非连续的内存区。

 

那么,vmalloc_init函数就是为第5)项——非连续内存区管理进行初始化。非连续内存区保留的线性地址空间的起始地址由VMALLOC_START宏定义,而末尾地址由VMALLOC_END 宏定义:

#define VMALLOC_START  ((unsigned long)high_memory + VMALLOC_OFFSET)

# define VMALLOC_END    (PKMAP_BASE - 2 * PAGE_SIZE)

 

关于非连续内存区的相关知识,请查阅博客“非连续内存区”

http://blog.csdn.net/yunsongice/archive/2010/04/27/5536197.aspx

相关内容。

你可能感兴趣的:(list,cache,struct,insert,import,each)