再读linux内核存储管理系统完整打印版.docx

上传人:b****6 文档编号:8188715 上传时间:2023-01-29 格式:DOCX 页数:92 大小:62.41KB
下载 相关 举报
再读linux内核存储管理系统完整打印版.docx_第1页
第1页 / 共92页
再读linux内核存储管理系统完整打印版.docx_第2页
第2页 / 共92页
再读linux内核存储管理系统完整打印版.docx_第3页
第3页 / 共92页
再读linux内核存储管理系统完整打印版.docx_第4页
第4页 / 共92页
再读linux内核存储管理系统完整打印版.docx_第5页
第5页 / 共92页
点击查看更多>>
下载资源
资源描述

再读linux内核存储管理系统完整打印版.docx

《再读linux内核存储管理系统完整打印版.docx》由会员分享,可在线阅读,更多相关《再读linux内核存储管理系统完整打印版.docx(92页珍藏版)》请在冰豆网上搜索。

再读linux内核存储管理系统完整打印版.docx

再读linux内核存储管理系统完整打印版

再读内核存储管理

(1):

相关的全局变量

1.1   相关的全局变量

  1.1.1  _ramstart,_ramend,_rambase

  这三个全局变量的定义在head.s文件中:

/*

 *SetuptheusableofRAMstuff.SizeofRAMisdeterminedthen

 *aninitialstacksetupattheend.

 */

 

.align4

__rambase:

.long  0

__ramstart:

.long  0

__ramend:

.long  0

  为了在C文件中使用它们,在include/asm/bfin-global.h中做了一个声明:

  externunsignedlong_ramstart,_ramend,_rambase;

  然后在setup_arch函数中对它们进行了初始化:

    _ramend=CONFIG_MEM_SIZE*1024*1024;

    _ramstart=(unsignedlong)__bss_stop;

    _rambase=(unsignedlong)_stext;

  在这里__bss_stop是在ldf文件中定义:

     bsz_sdramZERO_INIT

     {

              …

        INPUT_SECTION_ALIGN(4)

        .=(.+3)/4*4;

              ___bss_stop=.;

              __end=.;

              

     }>MEM_SDRAM

  而bsz_sdram是内核中的最后一个段,因此_ramstart将指向内核之后的第一个可用字节。

  _stext也是在ldf文件中定义的一个变量:

       .text

       {

        INPUT_SECTION_ALIGN(4)

        .=(.+3)/4*4;

              __text=.;

              _text=.;

              __stext=.;

              …….

 

        INPUT_SECTION_ALIGN(4)

        .=(.+3)/4*4;

              __etext=.;

       }>MEM_SDRAM_TEXT

而.text是内核中排在最前面的一个段,因此_rambase将指向内核的起始位置。

  在这里还需要注意_ramend的定义,虽然在这里给它赋了一个固定的值,但是通过引导程序设定启动参数可以进行更改,如引导程序使用

  mem=32m

  的时候,将会在parse_cmdline_early函数中触发下面的代码:

             if(!

memcmp(to,"mem=",4)){

                  to+=4;

                  memsize=memparse(to,&to);

                  if(memsize)

                      _ramend=memsize;

 

             }elseif(!

memcmp(to,"max_mem=",8)){

….

  从而将这个值更改。

  1.1.2  memory_start和memory_end

  这两个全局变量几乎都是同时使用的,它们的定义在arch/blackfin/kernel/setup.c中:

  unsignedlongmemory_start,memory_end,physical_mem_end;

  在setup_arch函数中对它们做了初始化工作:

    memory_start=PAGE_ALIGN(_ramstart);

/*toalignthepointertothe(next)pageboundary*/

#definePAGE_ALIGN(addr)   (((addr)+PAGE_SIZE-1)&PAGE_MASK)

  即memory_start指向内核结束的位置,但是向上做了页对齐(4K)。

    /*bynowthestackispartoftheinittask*/

    memory_end=_ramend-DMA_UNCACHED_REGION;

#ifdefined(CONFIG_DMA_UNCACHED_2M)

#defineDMA_UNCACHED_REGION(2*1024*1024)

#elifdefined(CONFIG_DMA_UNCACHED_1M)

#defineDMA_UNCACHED_REGION(1024*1024)

#else

#defineDMA_UNCACHED_REGION(0)

#endif

即memory_end指向可用物理内存的最高位置。

  当没有启用MTD的时候,还有下面一段代码:

#if(defined(CONFIG_BFIN_ICACHE)&&ANOMALY_05000263)

    /*DuetoaHardwareAnomalyweneedtolimitthesizeofusable

     *instructionmemorytomax60MB,56ifHUNT_FOR_ZEROison

     *05000263-HardwareloopcorruptedwhentakinganICPLBexception

     */

#if(defined(CONFIG_DEBUG_HUNT_FOR_ZERO))

    if(memory_end>=56*1024*1024)

        memory_end=56*1024*1024;

#else

    if(memory_end>=60*1024*1024)

        memory_end=60*1024*1024;

#endif                /*CONFIG_DEBUG_HUNT_FOR_ZERO*/

    printk(KERN_NOTICE"Warning:

limitingmemoryto%liMBduetohardwareanomaly05000263\n",memory_end>>20);

#endif                /*ANOMALY_05000263*/

  此时,由于ANOMALY_05000263的缘故,memory_end将被限制为60M,即0x03c00000。

  #if!

defined(CONFIG_MTD_UCLINUX)

  memory_end-=SIZE_4K;/*IncasethereisnovalidCPLBbehindmemory_endmakesurewedon'tgettoclose*/

  #endif

  由此,memory_end的值变为0x03bff000。

且不再改变。

  当启用了MTD的时候,memory_end将指向物理内存减去RAMDISK大小的位置。

  1.1.3  nr_kernel_pages与nr_all_pages

这两个值的定义都在mm/page_alloc.c中:

unsignedlong__meminitdatanr_kernel_pages;

unsignedlong__meminitdatanr_all_pages;

  在free_area_init_core这个初始化函数中对它们赋初值:

staticvoid__meminitfree_area_init_core(structpglist_data*pgdat,

        unsignedlong*zones_size,unsignedlong*zholes_size)

{

   …

   

    for(j=0;j

        structzone*zone=pgdat->node_zones+j;

        unsignedlongsize,realsize,memmap_pages;

 

        //size=realsize=SDRAM的页表数量,对MSDRAM,其值为x3fff

        size=zone_spanned_pages_in_node(nid,j,zones_size);

        realsize=size-zone_absent_pages_in_node(nid,j,

                                    zholes_size);

 

        /*

         *Adjustrealsizesothatitaccountsforhowmuchmemory

         *isusedbythiszoneformemmap.Thisaffectsthewatermark

         *andper-cpuinitialisations

         */

        memmap_pages=(size*sizeof(structpage))>>PAGE_SHIFT;

        if(realsize>=memmap_pages){

             realsize-=memmap_pages;

             printk(KERN_DEBUG

                  "%szone:

%lupagesusedformemmap\n",

                  zone_names[j],memmap_pages);

        }else

             printk(KERN_WARNING

                  "%szone:

%lupagesexceedsrealsize%lu\n",

                  zone_names[j],memmap_pages,realsize);

 

        /*Accountforreservedpages*/

        //dma_reserve的值可以从引导程序导入,在此为0

        if(j==0&&realsize>dma_reserve){

             realsize-=dma_reserve;

             printk(KERN_DEBUG"%szone:

%lupagesreserved\n",

                      zone_names[0],dma_reserve);

        }

 

        //is_highmem_idx恒为

        if(!

is_highmem_idx(j))

             nr_kernel_pages+=realsize;

        nr_all_pages+=realsize;

         ….

 

    }

}

从上述代码可以看出,这两个值都表示可用的页的数量,其表示的内存范围从0到60M,不包含page数组所占用的页。

对于64MSDRAM(实际限制为60M),不启用MTD的情况,其值为0x3b6a。

  1.1.4  mem_map

  这个全局变量的定义在mm/nommu.c中:

  structpage*mem_map;

  在内核中每个4K的页都有一个structpage与之相对应,而mem_map就是指向这个page数组的头指针。

  它的初始化由alloc_node_mem_map完成:

staticvoid__init_refokalloc_node_mem_map(structpglist_data*pgdat)

{

    /*ia64getsitsownnode_mem_map,beforethis,withoutbootmem*/

    if(!

pgdat->node_mem_map){

        unsignedlongsize,start,end;

        structpage*map;

 

        /*

         *Thezone'sendpointsaren'trequiredtobeMAX_ORDER

         *alignedbutthenode_mem_mapendpointsmustbeinorder

         *forthebuddyallocatortofunctioncorrectly.

         */

        start=pgdat->node_start_pfn&~(MAX_ORDER_NR_PAGES-1);

        end=pgdat->node_start_pfn+pgdat->node_spanned_pages;

        end=ALIGN(end,MAX_ORDER_NR_PAGES);

        size=(end-start)*sizeof(structpage);

        map=alloc_remap(pgdat->node_id,size);

        if(!

map)

             map=alloc_bootmem_node(pgdat,size);

        pgdat->node_mem_map=map+(pgdat->node_start_pfn-start);

    }

    /*

     *WithnoDISCONTIG,theglobalmem_mapisjustsetasnode0's

     */

    if(pgdat==NODE_DATA(0)){

        mem_map=NODE_DATA(0)->node_mem_map;

    }

}

  从这个函数可以看出,它的值与pglist_data中的node_mem_map成员相同。

  在这里pgdat指向全局唯一的pglist_data:

  externstructpglist_datacontig_page_data;

  pgdat->node_start_pfn的值为0。

  pgdat->node_spanned_pages的值为整个SDRAM中的页(4K)数量。

  1.1.5  contig_page_data

  内核支持所谓的NUMA结构,它将整个系统的存储空间分成几个不连续的节点,每个节点用一个pglist_data进行描述,再将这些节点放在一个链表中,但在BF561系统内核中定义了一个叫NODE_DATA的宏,它的定义在include/linux/mmzone.h中

externstructpglist_datacontig_page_data;

#defineNODE_DATA(nid)     (&contig_page_data)

  从这个定义可以看出,在内核中实际只有一个pglist_data。

即contig_page_data。

  1.1.6  vm_total_pages

  这个值的定义在mm/vmscan.c中:

  longvm_total_pages;  /*ThetotalnumberofpageswhichtheVMcontrols*/

  它表示内存的可用页数,其初始化由

void__meminitbuild_all_zonelists(void)

{

   …

    vm_total_pages=nr_free_pagecache_pages();

    printk("Built%izonelists.Totalpages:

%ld\n",

             num_online_nodes(),vm_total_pages);

}

  函数完成,对于64M内存(实际限制为60M),其值将为0x3b6a。

再读内核存储管理

(2):

相关的数据结构

1.1   相关的数据结构

  1.1.1  pglist_data

  pglist_data的定义在include/linux/mmzone.h中:

 

/*

 *Thepg_data_tstructureisusedinmachineswithCONFIG_DISCONTIGMEM

 *(mostlyNUMAmachines?

)todenoteahigher-levelmemoryzonethanthe

 *zonedenotes.

 *

 *OnNUMAmachines,eachNUMAnodewouldhaveapg_data_ttodescribe

 *it'smemorylayout.

 *

 *Memorystatisticsandpagereplacementdatastructuresaremaintainedona

 *per-zonebasis.

 */

structbootmem_data;

typedefstructpglist_data{

    structzonenode_zones[MAX_NR_ZONES];

    structzonelistnode_zonelists[MAX_NR_ZONES];

    intnr_zones;

    structpage*node_mem_map;

    structbootmem_data*bdata;

    unsignedlongnode_start_pfn;

    unsignedlongnode_present_pages;/*totalnumberofphysicalpages*/

    unsignedlongnode_spanned_pages;/*totalsizeofphysicalpage

                           range,includingholes*/

    intnode_id;

    wait_queue_head_tkswapd_wait;

    structtask_struct*kswapd;

    intkswapd_max_order;

}pg_data_t;

  这个结构体用于描述可用存储空间的情况。

  l        bdata

staticbootmem_data_tcontig_bootmem_data;

structpglist_datacontig_page_data={.bdata=&contig_bootmem_data};

从这个定义还可以看出在这个结构体中,bdata实际将指向一个固定的位置contig_bootmem_data且在mem_init函数调用后此成员将不再使用。

  l        zone

  对于这个结构体中的zone,内核实际只使用了ZONE_DMA(0)这个区域,它的范围从内核代码结束一直到物理内存结束。

  l        node_id

  因为整个内核只使用了一个NODE,因此在这个结构体中node_id的值将为0。

  l        node_start_pfn

  将为0。

  l        node_spanned_pages和node_present_pages

  两个成员的初始化在calculate_node_totalpages函数中完成,它们的值为SDRAM的页表数量,包含未用的区域和内核代码等,其值相等。

对于64M内存而言(实际限制到60M),其值为0x3bff。

  l        node_mem_map

  在内核中每个4K的页都有一个structpage结构体与之对应,这个成员指向这个page数组的首地址,它将在初始化时由alloc_node_mem_map函数进行空间分配(使用bootmem)。

  l        nr_zones

  这个值用于表示可用的zone的最高序号+1。

对于BF561而言,只使用了ZONE_DMA,因此这个值将为1。

  1.1.2  per_cpu_pageset

  这个结构体的定义在include/linux/mmzone.h中:

enumzone_stat_item{

    /*First128bytecacheline(assuming64bitwords)*/

    NR_FREE_PAGES,

    NR_INACTIVE,

    NR_ACTIVE,

    NR_ANON_PAGES,    /*Mappedanonymouspages*/

    NR_FILE_MAPPED,   /*pagecachepagesmappedintopagetables.

                onlymodifiedfromprocesscontext*/

    NR_FILE_PAGES,

    NR_FILE_DIRTY,

    NR_WRITEBACK,

    /*Second128bytecacheline*/

    

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1