Linux伙伴系统(二)--伙伴系统的初始化

水平有限,描述不当之处还请指出,转载请注明出处http://blog.csdn.net/vanbreaker/article/details/7611585 

      伙伴系统的初始化主要是初始化之前介绍的伙伴系统涉及到的数据结构,并且把系统初始化时由bootmem allocator管理的低端内存以及系统的高端内存释放到伙伴系统中去。其中有些和zone相关的域在前面<<Linux节点和内存管理区的初始化>>中已经有所介绍。

        在start_kernel()-->paging_init()-->zone_sizes_init()-->free_area_init_nodes()-->free_area_init_node()-->free_area_init_core()-->init_currently_empty_zone()-->zone_init_free_lists()中,free_area的相关域都被初始化

[cpp]  view plain copy
  1. static void __meminit zone_init_free_lists(struct zone *zone)  
  2. {  
  3.     int order, t;  
  4.     for_each_migratetype_order(order, t) {  
  5.         /*链表初始化为空链表*/  
  6.         INIT_LIST_HEAD(&zone->free_area[order].free_list[t]);  
  7.         /*内存块数量初始化为0*/  
  8.         zone->free_area[order].nr_free = 0;  
  9.     }  
  10. }  


for_each_migratetype_order(order, t)就是两个嵌套的for循环

[cpp]  view plain copy
  1. #define for_each_migratetype_order(order, type) \  
  2.     for (order = 0; order < MAX_ORDER; order++) \  
  3.         for (type = 0; type < MIGRATE_TYPES; type++)  


start_kernel()-->mm_init()-->mem_init(),负责统计所有可用的低端内存和高端内存,并释放到伙伴系统中

<Init_32.c>

[cpp]  view plain copy
  1. void __init mem_init(void)  
  2. {  
  3.     int codesize, reservedpages, datasize, initsize;  
  4.     int tmp;  
  5.   
  6.     pci_iommu_alloc();  
  7.   
  8. #ifdef CONFIG_FLATMEM  
  9.     BUG_ON(!mem_map);  
  10. #endif  
  11.     /* this will put all low memory onto the freelists */  
  12.      /*销毁bootmem分配器,释放bootmem分配器管理的空闲页框和bootmem的位图所占用的页框, 
  13.          并计入totalram_pages*/  
  14.     totalram_pages += free_all_bootmem();  
  15.   
  16.     reservedpages = 0;  
  17.     for (tmp = 0; tmp < max_low_pfn; tmp++)  
  18.         /* 
  19.          * Only count reserved RAM pages: 
  20.          */  
  21.         if (page_is_ram(tmp) && PageReserved(pfn_to_page(tmp)))  
  22.             reservedpages++;  
  23.   
  24.     /*处理高端内存页框*/  
  25.     set_highmem_pages_init();  
  26.   
  27.     codesize =  (unsigned long) &_etext - (unsigned long) &_text;  
  28.     datasize =  (unsigned long) &_edata - (unsigned long) &_etext;  
  29.     initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;  
  30.   
  31.     printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, "  
  32.             "%dk reserved, %dk data, %dk init, %ldk highmem)\n",  
  33.         nr_free_pages() << (PAGE_SHIFT-10),  
  34.         num_physpages << (PAGE_SHIFT-10),  
  35.         codesize >> 10,  
  36.         reservedpages << (PAGE_SHIFT-10),  
  37.         datasize >> 10,  
  38.         initsize >> 10,  
  39.         (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))  
  40.            );  
  41.   
  42.     printk(KERN_INFO "virtual kernel memory layout:\n"  
  43.         "    fixmap  : 0x%08lx - 0x%08lx   (%4ld kB)\n"  
  44. #ifdef CONFIG_HIGHMEM  
  45.         "    pkmap   : 0x%08lx - 0x%08lx   (%4ld kB)\n"  
  46. #endif  
  47.         "    vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n"  
  48.         "    lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)\n"  
  49.         "      .init : 0x%08lx - 0x%08lx   (%4ld kB)\n"  
  50.         "      .data : 0x%08lx - 0x%08lx   (%4ld kB)\n"  
  51.         "      .text : 0x%08lx - 0x%08lx   (%4ld kB)\n",  
  52.         FIXADDR_START, FIXADDR_TOP,  
  53.         (FIXADDR_TOP - FIXADDR_START) >> 10,  
  54.   
  55. #ifdef CONFIG_HIGHMEM  
  56.         PKMAP_BASE, PKMAP_BASE+LAST_PKMAP*PAGE_SIZE,  
  57.         (LAST_PKMAP*PAGE_SIZE) >> 10,  
  58. #endif  
  59.   
  60.         VMALLOC_START, VMALLOC_END,  
  61.         (VMALLOC_END - VMALLOC_START) >> 20,  
  62.   
  63.         (unsigned long)__va(0), (unsigned long)high_memory,  
  64.         ((unsigned long)high_memory - (unsigned long)__va(0)) >> 20,  
  65.   
  66.         (unsigned long)&__init_begin, (unsigned long)&__init_end,  
  67.         ((unsigned long)&__init_end -  
  68.          (unsigned long)&__init_begin) >> 10,  
  69.   
  70.         (unsigned long)&_etext, (unsigned long)&_edata,  
  71.         ((unsigned long)&_edata - (unsigned long)&_etext) >> 10,  
  72.   
  73.         (unsigned long)&_text, (unsigned long)&_etext,  
  74.         ((unsigned long)&_etext - (unsigned long)&_text) >> 10);  
  75.   
  76.     /* 
  77.      * Check boundaries twice: Some fundamental inconsistencies can 
  78.      * be detected at build time already. 
  79.      */  
  80. #define __FIXADDR_TOP (-PAGE_SIZE)  
  81. #ifdef CONFIG_HIGHMEM  
  82.     BUILD_BUG_ON(PKMAP_BASE + LAST_PKMAP*PAGE_SIZE  > FIXADDR_START);  
  83.     BUILD_BUG_ON(VMALLOC_END            > PKMAP_BASE);  
  84. #endif  
  85. #define high_memory (-128UL << 20)  
  86.     BUILD_BUG_ON(VMALLOC_START          >= VMALLOC_END);  
  87. #undef high_memory  
  88. #undef __FIXADDR_TOP  
  89.   
  90. #ifdef CONFIG_HIGHMEM  
  91.     BUG_ON(PKMAP_BASE + LAST_PKMAP*PAGE_SIZE    > FIXADDR_START);  
  92.     BUG_ON(VMALLOC_END              > PKMAP_BASE);  
  93. #endif  
  94.     BUG_ON(VMALLOC_START                >= VMALLOC_END);  
  95.     BUG_ON((unsigned long)high_memory       > VMALLOC_START);  
  96.   
  97.     if (boot_cpu_data.wp_works_ok < 0)  
  98.         test_wp_bit();  
  99.   
  100.     save_pg_dir();  
  101.     /*将前3GB线性地址(即用户地址空间)对应的pgd全局目录项清空*/  
  102.     zap_low_mappings(true);  
  103. }  


 

free_all_bootmem()的核心函数在<<bootmem allocator>>中已有介绍,这里不再列出

 

<Highmem_32.c>

[cpp]  view plain copy
  1. void __init set_highmem_pages_init(void)  
  2. {  
  3.     struct zone *zone;  
  4.     int nid;  
  5.   
  6.     for_each_zone(zone) {/*遍历每个管理区*/  
  7.         unsigned long zone_start_pfn, zone_end_pfn;  
  8.   
  9.         if (!is_highmem(zone))/*判断是否是高端内存管理区*/  
  10.             continue;  
  11.   
  12.         /*记录高端内存管理区的起始页框号和结束页框号*/  
  13.         zone_start_pfn = zone->zone_start_pfn;  
  14.         zone_end_pfn = zone_start_pfn + zone->spanned_pages;  
  15.   
  16.         nid = zone_to_nid(zone);  
  17.         printk(KERN_INFO "Initializing %s for node %d (%08lx:%08lx)\n",  
  18.                 zone->name, nid, zone_start_pfn, zone_end_pfn);  
  19.   
  20.         /*将高端内存的页框添加到伙伴系统*/  
  21.         add_highpages_with_active_regions(nid, zone_start_pfn,  
  22.                  zone_end_pfn);  
  23.     }  
  24.     /*将释放到伙伴系统的高端内存页框数计入totalram_pages*/  
  25.     totalram_pages += totalhigh_pages;  
  26. }  


 

[cpp]  view plain copy
  1. void __init add_highpages_with_active_regions(int nid, unsigned long start_pfn,  
  2.                           unsigned long end_pfn)  
  3. {  
  4.     struct add_highpages_data data;  
  5.   
  6.     data.start_pfn = start_pfn;  
  7.     data.end_pfn = end_pfn;  
  8.   
  9.     /*遍历所有的活动区,调用add_highpages_word_fn()来处理每个活动区*/  
  10.     work_with_active_regions(nid, add_highpages_work_fn, &data);  
  11. }  


 

[cpp]  view plain copy
  1. <span style="font-size:12px;">void __init work_with_active_regions(int nid, work_fn_t work_fn, void *data)  
  2. {  
  3.     int i;  
  4.     int ret;  
  5.   
  6.     for_each_active_range_index_in_nid(i, nid) {  
  7.         ret = work_fn(early_node_map[i].start_pfn,  
  8.                   early_node_map[i].end_pfn, data);  
  9.         if (ret)  
  10.             break;  
  11.     }  
  12. }</span>  

 

[cpp]  view plain copy
  1. <span style="font-size:12px;">static int __init add_highpages_work_fn(unsigned long start_pfn,  
  2.                      unsigned long end_pfn, void *datax)  
  3. {  
  4.     int node_pfn;  
  5.     struct page *page;  
  6.     unsigned long final_start_pfn, final_end_pfn;  
  7.     struct add_highpages_data *data;  
  8.   
  9.     data = (struct add_highpages_data *)datax;  
  10.   
  11.     /*得到合理的起始结束页框号*/  
  12.     final_start_pfn = max(start_pfn, data->start_pfn);  
  13.     final_end_pfn = min(end_pfn, data->end_pfn);  
  14.     if (final_start_pfn >= final_end_pfn)  
  15.         return 0;  
  16.   
  17.     /*遍历活动区的页框*/  
  18.     for (node_pfn = final_start_pfn; node_pfn < final_end_pfn;  
  19.          node_pfn++) {  
  20.         if (!pfn_valid(node_pfn))  
  21.             continue;  
  22.         page = pfn_to_page(node_pfn);  
  23.         add_one_highpage_init(page, node_pfn);/*将该页框添加到伙伴系统*/  
  24.     }  
  25.   
  26.     return 0;  
  27.   
  28. }  
  29. </span>  


 

[cpp]  view plain copy
  1. <span style="font-size:12px;">static void __init add_one_highpage_init(struct page *page, int pfn)  
  2. {  
  3.     ClearPageReserved(page);  
  4.     init_page_count(page);/*count初始化为1*/  
  5.     __free_page(page);     /*释放page到伙伴系统*/  
  6.     totalhigh_pages++;      /*高端内存的页数加1*/  
  7. }</span>  


__free_page()中涉及到的具体操作在后面介绍伙伴系统释放页面时再做分析

 

 

在free_area_init_core()-->memmap_init()(-->memmap_init_zone() )-->set_pageblock_migratetype(),将每个pageblock的起始页框对应的struct zone当中的pageblock_flags代表的位图相关区域标记为可移动的,表示该pageblock为可移动的,也就是说内核初始化伙伴系统时,所有的页都被标记为可移动的

[cpp]  view plain copy
  1. <span style="font-size:12px;">void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,  
  2.         unsigned long start_pfn, enum memmap_context context)  
  3. {  
  4.     struct page *page;  
  5.     unsigned long end_pfn = start_pfn + size;  
  6.     unsigned long pfn;  
  7.     struct zone *z;  
  8.   
  9.     if (highest_memmap_pfn < end_pfn - 1)  
  10.         highest_memmap_pfn = end_pfn - 1;  
  11.   
  12.     z = &NODE_DATA(nid)->node_zones[zone];  
  13.     for (pfn = start_pfn; pfn < end_pfn; pfn++) {  
  14.         /* 
  15.          * There can be holes in boot-time mem_map[]s 
  16.          * handed to this function.  They do not 
  17.          * exist on hotplugged memory. 
  18.          */  
  19.         if (context == MEMMAP_EARLY) {  
  20.             if (!early_pfn_valid(pfn))  
  21.                 continue;  
  22.             if (!early_pfn_in_nid(pfn, nid))  
  23.                 continue;  
  24.         }  
  25.         page = pfn_to_page(pfn);  
  26.         set_page_links(page, zone, nid, pfn);  
  27.         mminit_verify_page_links(page, zone, nid, pfn);  
  28.         init_page_count(page);  
  29.         reset_page_mapcount(page);  
  30.         SetPageReserved(page);  
  31.         /* 
  32.          * Mark the block movable so that blocks are reserved for 
  33.          * movable at startup. This will force kernel allocations 
  34.          * to reserve their blocks rather than leaking throughout 
  35.          * the address space during boot when many long-lived 
  36.          * kernel allocations are made. Later some blocks near 
  37.          * the start are marked MIGRATE_RESERVE by 
  38.          * setup_zone_migrate_reserve() 
  39.          * 
  40.          * bitmap is created for zone's valid pfn range. but memmap 
  41.          * can be created for invalid pages (for alignment) 
  42.          * check here not to call set_pageblock_migratetype() against 
  43.          * pfn out of zone. 
  44.          */  
  45.          /*如果pfn处在合理的范围,并且该pfn是一个pageblock的起始页框号*/  
  46.         if ((z->zone_start_pfn <= pfn)  
  47.             && (pfn < z->zone_start_pfn + z->spanned_pages)  
  48.             && !(pfn & (pageblock_nr_pages - 1)))  
  49.             set_pageblock_migratetype(page, MIGRATE_MOVABLE);/*将页框对应的位图域标记为可移动的*/  
  50.   
  51.         INIT_LIST_HEAD(&page->lru);  
  52. #ifdef WANT_PAGE_VIRTUAL  
  53.         /* The shift won't overflow because ZONE_NORMAL is below 4G. */  
  54.         if (!is_highmem_idx(zone))  
  55.             set_page_address(page, __va(pfn << PAGE_SHIFT));  
  56. #endif  
  57.     }  
  58. }  
  59. </span>  


    

 

[cpp]  view plain copy
  1. <span style="font-size:12px;">static void set_pageblock_migratetype(struct page *page, int migratetype)  
  2. {  
  3.   
  4.     /*如果没有开启移动性分类,则所有页都要标记为不可移动的*/  
  5.     if (unlikely(page_group_by_mobility_disabled))  
  6.         migratetype = MIGRATE_UNMOVABLE;  
  7.       
  8.     set_pageblock_flags_group(page, (unsigned long)migratetype,  
  9.                     PB_migrate, PB_migrate_end);  
  10. }  
  11. </span>  


 

[cpp]  view plain copy
  1. void set_pageblock_flags_group(struct page *page, unsigned long flags,  
  2.                     int start_bitidx, int end_bitidx)  
  3. {  
  4.     struct zone *zone;  
  5.     unsigned long *bitmap;  
  6.     unsigned long pfn, bitidx;  
  7.     unsigned long value = 1;  
  8.   
  9.     zone = page_zone(page);  
  10.     pfn = page_to_pfn(page);  
  11.     /*得到位图的起始地址,即zone->pageblock_flags*/  
  12.     bitmap = get_pageblock_bitmap(zone, pfn);  
  13.     /*得到pfn对应的位图区域的偏移量*/  
  14.     bitidx = pfn_to_bitidx(zone, pfn);  
  15.     VM_BUG_ON(pfn < zone->zone_start_pfn);  
  16.     VM_BUG_ON(pfn >= zone->zone_start_pfn + zone->spanned_pages);  
  17.   
  18.     /*每个页都需要3个bit来表征其移动性,也就是从start_bitidx到end_bitidx共3位*/  
  19.     for (; start_bitidx <= end_bitidx; start_bitidx++, value <<= 1)  
  20.         if (flags & value)/*通过flags和value相与确定相关的位是否为1*/  
  21.             __set_bit(bitidx + start_bitidx, bitmap);  
  22.         else  
  23.             __clear_bit(bitidx + start_bitidx, bitmap);  
  24. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
NB-IoT无线网络系统优化指导书 目录 1总则 1 1.1编写说明 1 1.2缩略语 1 1.3编写依据 3 1.4版本更新历史 3 1.5指导书结构 3 2网络评估 5 2.1准备工作 5 2.1.1基站基础数据核查 5 2.1.2无线参数核查 5 2.1.3设备隐性故障排查 5 2.2网管指标评估 5 2.2.1概述 5 2.2.2呼叫接入类指标 5 2.2.3呼叫保持类指标 6 2.2.4业务流量类指标 6 2.2.5业务完整类指标 6 2.2.6资源负荷类指标 6 2.2.7设备可用性指标 7 2.3路测指标评估 7 2.3.1 DT测试方法 7 2.3.2 CQT评估 7 2.3.3覆盖类指标 8 2.3.4接入类指标 8 2.3.5完整类指标 8 2.3.6感知类指标 8 2.3.7移动性指标 8 2.4 N800&L800协同覆盖评估 9 2.5用户投诉评估 9 3覆盖干扰优化 10 3.1 NB-IOT覆盖增强理论 10 3.1.1 NB-IoT功率谱密度(PSD) 10 3.1.2重复(Repetition)增益 10 3.2基础优化方法 12 3.2.1基础优化流程 12 3.2.2 RF优化 15 3.2.3参数优化 16 3.2.4干扰排查 17 3.2.5异频组网策略 20 3.3 N800&L800协同优化 23 3.3.1利用L800进行N800网络问题评估 23 3.3.2 L800&N800协同优化案例 26 3.4覆盖干扰问题分析 30 3.4.1弱覆盖 30 3.4.2越区覆盖 31 3.4.3重叠覆盖 32 3.4.4上行覆盖受限 33 3.4.5上下行覆盖不平衡 33 3.4.6上行干扰 34 3.4.7下行干扰 34 3.4.8模三干扰 35 3.4.9其他问题 36 4异常事件优化 37 4.1 RRC连接建立失败 37 4.1.1 RRC连接建立流程 37 4.1.2 RRC连接建立失败现象 39 4.1.3 RRC连接失败定位流程 40 4.1.4 RRC连接失败常见原因 43 4.2 ATTACH附着失败 43 4.2.1 Attach附着流程 43 4.2.2 Attach附着失败现象 44 4.2.3 Attach失败定位流程 45 4.2.4 Attach失败常见原因 46 4.3重选失败 47 4.3.1小区重选流程 47 4.3.2小区重选失败现象 47 4.3.3小区重选失败定位流程 48 4.3.4小区重选失败常见原因 50 4.3.5路测参数配置建议值 50 4.4空口掉线 52 4.4.1 UE上下文释放流程 52 4.4.2空口掉线现象 53 4.4.3空口掉线定位流程 54 4.4.4空口掉线常见原因 55 4.5故障排查常用工具 55 4.5.1华为网管工具 55 4.5.2中兴网管工具 68 5功耗优化 76 5.1无线侧参数 76 5.1.1默认寻呼周期 76 5.1.2 UE不活动定时器 76 5.1.3 DRX特性开关 76 5.1.4前导初始接收目标功率值 77 5.1.5功率攀升步长 77 5.1.6 NPRACH前导重复次数 77 5.1.7上行初始传输重复次数 78 5.1.8路径损耗因子 78 5.1.9 NPUSCH标称P0值 78 5.1.10消息3相对前导的功率偏置 79 5.2核心侧参数(中兴) 79 5.2.1 Active Time(T3324)(s) 79 5.2.2 MME本地配置的周期性跟踪区更新定时器(T3412)时长(秒) 79 5.2.3 NB PTW Value 80 5.3核心网参数(华为) 80 5.3.1 PSM开关 80 5.3.2 Active Timer定时器时长 80 5.3.3 eDRX开关 81 5.3.4窄带S1模式寻呼时间窗口时长 81 5.3.5窄带S1模式寻呼周期 81 6关键参数配置 82 6.1系统配置类 82 6.1.1参考信号功率 82 6.1.2 SI重复传输模式 82 6.1.3 SI无线帧偏移 82 6.1.4 SI窗口长度 83 6.1.5 SIB1重复次数 83 6.1.6 SIB2周期 83 6.1.7 SIB3周期 83 6.1.8 SIB4周期 84 6.1.9 SIB5周期 84 6.1.10 SIB14周期 84 6.2小区选择类 85 6.2.1最低接收电平 85 6.2.2最低接入信号质量 85 6.3小区重选类 85 6.3.1同频测量门限配置指示 85 6.3.2同频测量启动门限 86 6.3.3最低接收电平 86 6.3.4同频重选时间 86 6.3.5同频小区重选设置 87 6.3.6异频/异系统测量启动门限配置指示 87 6.3.7异频/

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值