再读linux内核存储管理系统完整打印版.docx
- 文档编号:8188715
- 上传时间:2023-01-29
- 格式:DOCX
- 页数:92
- 大小:62.41KB
再读linux内核存储管理系统完整打印版.docx
《再读linux内核存储管理系统完整打印版.docx》由会员分享,可在线阅读,更多相关《再读linux内核存储管理系统完整打印版.docx(92页珍藏版)》请在冰豆网上搜索。
再读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*/
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 再读 linux 内核 存储 管理 系统 完整 打印
![提示](https://static.bdocx.com/images/bang_tan.gif)