Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1030604
  • 博文数量: 123
  • 博客积分: 5051
  • 博客等级: 大校
  • 技术积分: 1356
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-14 10:56
文章分类
文章存档

2012年(1)

2011年(21)

2010年(13)

2009年(55)

2008年(33)

分类: LINUX

2009-05-03 16:18:57

下面将介绍start_kernel关于每个内存初始化函数。
   
在内核启动函数中,使用全局变量kernel_param即内核参数,同时调用了下面的内存初始化函数:

        page_address_init()//这个函数初始化页地址,使用链表将其链接起来。   

        setup_arch()//内存初始化,这个函数是相当重要的,下面将详细地对这个函数进行功能上的总结。

        这个函数设置了cpu引导数据,对前期CPU数据进行了初始化,以及对一些硬件数据进行了设置,(这里所讨论的一切都是i386体系结构中进行讨论的,而且内存设为1GB)。同时设置了全局变量max_low_pfn,所调用的函数是setup_memory()(这个函数设置了min_low_pfn全局变量,min_low_pfn=0,还设置了全局变量max_low_pfn=896MB/4KB以及max_pfn=1GB/4kb,highstart_pfn=max_low_pfn,highend_pfn=max_pfn,这里的highstart_pfn以及highend_pfn使用来进行高端内核空间页面的记录的。最后,这个函数调用了函数setup_bootmem_allocator()函数,对于这个函数的详细解释在后面章节会说到,就是设置了引导内存bootmem的设置)。之后,一个相当有意思且非常重要的函数paging_init()函数被调用来初始化页表。同时还调用了zone_sizes_init()来初始化节点数据和zone数据。在执行完setup_arch()之后,节点管理数据node_data[0]初始化完毕,同时三个管理区的各个数据段也初始化完毕,这时,就开始setup_per_cpu_area()函数。但是这个函数在单个CPU系统中为
空操作,就直接过渡到build_all_zonelists().    setup_per_cpu_areas();CPU系统中为空操作
    build_all_zonelists();
这个函数调用函数set_zonelist_order()current_zonelist_order设置为2
    page_alloc_init();
    cpuset_init_early();
    mem_init();
    kmem_cache_init();
    setup_per_cpu_pageset();
    pgtable_cache_init();
    proc_caches_init();
    cpuset_init();

    paging_init
函数的作用详解:
       
调用函数pagetable_init函数来为内核映射建立适当的页表,在这个函数被调用执行之前,系统一直是运行在引导进程所构造的页表中的。如果我们是在本地硬件进行引导的,那么这个页表则是在head.S文件中构造的,并且不运行在PAE模式下。这个页表的根是swapper_pg_dir,任何情况下paravirt_pagetable_setup_start()将会为其余的初始化工作进行适当地设置。pagetable_init函数调用kernel_physical_mapping_init函数初始化内核物理页表的映射,这个映射是最终映射。同时调用了page_table_range_init来对固定内存
进行了相应的映射处理以及permanent_kmaps_init()作永久内核映射初始化。
    zone_sizes_init
       
这个函数调用add_active_range()函数实现对全局变量early_node_map数组的初始化,初始化的数据结果为:
       
这个函数的结果为:
        3120         early_node_map[i].nid = nid=0;
        3121         early_node_map[i].start_pfn = start_pfn=0;
        3122         early_node_map[i].end_pfn = end_pfn=highend_pfn;
        3123         nr_nodemap_entries = i + 1=1;
       
同时调用函数free_area_init_nodes()函数(即初始化节点的空闲区域),函数free_area_init_nodes()初始化所有
的节点链表和管理数据区,这个函数将会为每一个活动节点调用free_area_init_node进行处理。并使用add_active_range函数所提供
的数据来计算每个节点的每个管理区以及对应洞的大小。free_area_init_node函数设置了节点的node_id值以及节点node起始页表号
。同时计算了节点的页表总数,调用calculate_node_totalpages()计算节点的总页数,并在caculate_node_totalpages()函数中设置
node_data[0]->node_spanned_pagesnode_data[0]->node_present_pages,这里的node_data[0]是一全局变量,用来跟踪节点信息.caculate_spanned_pages中计算了包含洞节点的大小以及不包含动节点的大小。分别使用上面的两个变量来记录。之后调用函数alloc_node_mem_map(),alloc_node_mem_map()函数中有一个全局变量node_remap_alloc_vaddr.这个函数为页描述符分配空间。并将所分配的装载页描述符的起始地址赋给全局变量mem_mapmem_map是在/linux/mm/memory.c文件中定义的全局变量,用来进行页描述符的管理的。接着zone_sizes_init()调用函数free_area_init_core来设置管理区数据结构。这里又引入了一个全局变量zone,这个函数的工作就是初始化这个全局变量。在这个函数中初始化了节点锁node_data[0]->node_size_lock,初始化了kswapd换出守护进程使用的等待队列node_data[0]->kswapd_wait,将kswapd将要创建的空闲块大小取对数的值初始化为0,并使用一个for环来设置三个管理区的各个数据段。到此为止,zone_sizes_init的工作已经完成了。

阅读(1985) | 评论(1) | 转发(0) |
0

上一篇:cpuid指令2

下一篇:head.s内存初始化数据

给主人留下些什么吧!~~

chinaunix网友2009-06-16 17:54:54

“这时,就开始setup_per_cpu_area()函数。但是这个函数在单个CPU系统中为 空操作。。。。” LZ确定单cpu时此函数为空操作吗? 空操作的意思即为,不为单cpu分配内存空间?? 最近也在看这一块 感觉这一点和LZ的理解有偏差 例如:/proc/diskstats 虚拟文件下的数据就是在io操作完成后,通过per_cpu_ptr()方法将所需的值添加到每个cpu对应的缓存区(具体在_disk_stats_add方法中调用的) 如果按LZ所言 那岂不是单cpu时不会保存这些数据 然后/proc下也就取不到这些数据了?? 不知道是不是我理解有错误~~~ 愿与LZ探讨~~