linux page.docx
- 文档编号:29225092
- 上传时间:2023-07-21
- 格式:DOCX
- 页数:19
- 大小:24.03KB
linux page.docx
《linux page.docx》由会员分享,可在线阅读,更多相关《linux page.docx(19页珍藏版)》请在冰豆网上搜索。
linuxpage
Linux支持非一致内存访问(Non-UniformMemoryAccess,NUMA)模型,在这种模型中,给定CPU对不同内存单元的访问时间可能不一样。
系统的物理内存被划分为几个节点。
在一个单独的节点内,任一给定CPU访问页面所需的时间都是相同的。
但是对不同的CPU,这个时间可能就不同。
对每个CPU而言,内核都试图把耗时节点的访问次数减到最少,这就需要小心地选择CPU最常引用的内核数据结构的存放位置。
每个节点中的物理内存又可以分为几个管理区(zone)。
在x86的体系结构下,Linux将内存分为3个管理区:
ZONE_DMA:
包含低于16M的内存页,因为ISA总线的DMA处理器有严格限制,只能对RAM的前16M进行寻址。
ZONE_NORMAL:
包含高于16M且低于896M的内存。
ZONE_HIGHMEM:
包含高于896M的内存。
对于BF561而言,DMA将可以访问整个内存区域,当然,由于anomaly-05000263的缘故,在启用ICACHE的情况下,可用内存将限制为60M。
所以在内核中,实际只使用了一个内存区,ZONE_DMA,在这个内存区中,包含了所有的内存范围。
下面试图通过对存储区域的初始化来分析下内核的数据表示。
1.1.1 相关数据结构
1.1.1.1 page
内核的存储管理是以page为单位的,每个page的大小为4K,且每个page都用一个page结构体来进行描述,这些page的描述做为一个数组放在内核代码之后。
因而这里就涉及到3个量:
一个是4K的实际页面的地址,即物理地址,在内核中表示为VirtualAddress;另一个为描述此页面的page结构指针,用page表示;还有一个是这个page结构体在整个page数组中的序号,内核称之为pfn。
这三个地址之间可以用6个宏来进行相互转换。
page结构体的定义在include/linux/mm_types.h中:
/*
*Eachphysicalpageinthesystemhasastructpageassociatedwith
*ittokeeptrackofwhateveritisweareusingthepageforatthe
*moment.Notethatwehavenowaytotrackwhichtasksareusing
*apage,thoughifitisapagecachepage,rmapstructurescantellus
*whoismappingit.
*/
structpage{
unsignedlongflags;/*Atomicflags,somepossibly
*updatedasynchronously*/
atomic_t_count;/*Usagecount,seebelow.*/
union{
atomic_t_mapcount;/*Countofptesmappedinmms,
*toshowwhenpageismapped
*&limitreversemapsearches.
*/
struct{/*SLUBuses*/
shortunsignedintinuse;
shortunsignedintoffset;
};
};
union{
struct{
unsignedlongprivate;/*Mapping-privateopaquedata:
*usuallyusedforbuffer_heads
*ifPagePrivateset;usedfor
*swp_entry_tifPageSwapCache;
*indicatesorderinthebuddy
*systemifPG_buddyisset.
*/
structaddress_space*mapping;/*Iflowbitclear,pointsto
*inodeaddress_space,orNULL.
*Ifpagemappedasanonymous
*memory,lowbitisset,and
*itpointstoanon_vmaobject:
*seePAGE_MAPPING_ANONbelow.
*/
};
spinlock_tptl;
struct{/*SLUBuses*/
void**lockless_freelist;
structkmem_cache*slab;/*Pointertoslab*/
};
struct{
structpage*first_page;/*Compoundpages*/
};
};
union{
pgoff_tindex;/*Ouroffsetwithinmapping.*/
void*freelist;/*SLUB:
freelistreq.slablock*/
};
structlist_headlru;/*Pageoutlist,eg.active_list
*protectedbyzone->lru_lock!
*/
};
● lru
这个结构体根据这个页面应用的不同有不同的含义,当此页面空闲时或者此页面用于高速缓存时,这个结构体用于将页面链接起来的双链表。
而当此页面用于SLAB算法时,它的next指针将指向这个slab所在的cache,即一个kmem_cache的结构体。
而其prev指针将指向这个slab。
这两个指针都是通过slab_map_pages函数进行设置的。
● flags
这个结构体中的flags成员每个位的定义在include/linux/page_flags.h中:
/*
*Variouspage->flagsbits:
*
*PG_reservedissetforspecialpages,whichcanneverbeswappedout.Some
*ofthemmightnotevenexist(egempty_bad_page)...
*
*ThePG_privatebitflagissetonpagecachepagesiftheycontainfilesystem
*specificdata(whichisnormallyatpage->private).Itcanbeusedby
*privateallocationsforitsownusage.
*
*DuringinitiationofdiskI/O,PG_lockedisset.ThisbitissetbeforeI/O
*andclearedwhenwriteback_starts_orwhenread_completes_.PG_writeback
*issetbeforewritebackstartsandclearedwhenitfinishes.
*
*PG_lockedalsopinsapageinpagecache,andblockstruncationofthefile
*whileitisheld.
*
*page_waitqueue(page)isawaitqueueofalltaskswaitingforthepage
*tobecomeunlocked.
*
*PG_uptodatetellswhetherthepage'scontentsisvalid.Whenaread
*completes,thepagebecomesuptodate,unlessadiskI/Oerrorhappened.
*
*PG_referenced,PG_reclaimareusedforpagereclaimforanonymousand
*file-backedpagecache(seemm/vmscan.c).
*
*PG_errorissettoindicatethatanI/Oerroroccurredonthispage.
*
*PG_arch_1isanarchitecturespecificpagestatebit.Thegenericcode
*guaranteesthatthisbitisclearedforapagewhenitfirstisenteredinto
*thepagecache.
*
*PG_highmempagesarenotpermanentlymappedintothekernelvirtualaddress
*space,theyneedtobekmappedseparatelyfordoingIOonthepages.The
*structpage(thesebitswithinformation)arealwaysmappedintokernel
*addressspace...
*
*PG_buddyissettoindicatethatthepageisfreeandinthebuddysystem
*(seemm/page_alloc.c).
*
*/
/*
*Don'tusethe*_dontuseflags.Usethemacros.Otherwiseyou'llbreak
*locked-anddirty-pageaccounting.
*
*Thepageflagsfieldissplitintotwoparts,themainflagsarea
*whichextendsfromthelowbitsupwards,andthefieldsareawhich
*extendsfromthehighbitsdownwards.
*
*|FIELD|...|FLAGS|
*N-1^0
*(N-FLAGS_RESERVED)
*
*Thefieldsareaisreservedforfieldsmappingzone,nodeandSPARSEMEM
*section.Theboundrybetweenthesetwoareasisdefinedby
*FLAGS_RESERVEDwhichdefinesthewidthofthefieldssection
*(seelinux/mmzone.h).Newflagsmust_not_overlapwiththisarea.
*/
#definePG_locked0/*Pageislocked.Don'ttouch.*/
#definePG_error1
#definePG_referenced2
#definePG_uptodate3
#definePG_dirty4
#definePG_lru5
#definePG_active6
#definePG_slab7/*slabdebug(Suparnawantsthis)*/
#definePG_owner_priv_18/*Owneruse.Ifpagecache,fsmayuse*/
#definePG_arch_19
#definePG_reserved10
#definePG_private11/*Ifpagecache,hasfs-privatedata*/
#definePG_writeback12/*Pageisunderwriteback*/
#definePG_compound14/*Partofacompoundpage*/
#definePG_swapcache15/*Swappage:
swp_entry_tinprivate*/
#definePG_mappedtodisk16/*Hasblocksallocatedon-disk*/
#definePG_reclaim17/*Tobereclaimedasap*/
#definePG_buddy19/*Pageisfree,onbuddylists*/
/*PG_owner_priv_1usersshouldhavedescriptivealiases*/
#definePG_checkedPG_owner_priv_1/*Usedbysomefilesystems*/
初始化时,flags都将初始化为PG_reserved。
对page的初始化过程可参见memmap_init_zone,位于mm/page_alloc.c:
/*
*Initiallyallpagesarereserved-freeonesarefreed
*upbyfree_all_bootmem()oncetheearlybootprocessis
*done.Non-atomicinitialization,single-pass.
*/
void__meminitmemmap_init_zone(unsignedlongsize,intnid,unsignedlongzone,
unsignedlongstart_pfn,enummemmap_contextcontext)
{
structpage*page;
unsignedlongend_pfn=start_pfn+size;
unsignedlongpfn;
for(pfn=start_pfn;pfn /* *Therecanbeholesinboot-timemem_map[]s *handedtothisfunction.Theydonot *existonhotpluggedmemory. */ if(context==MEMMAP_EARLY){ if(! early_pfn_valid(pfn)) continue; if(! early_pfn_in_nid(pfn,nid)) continue; } page=pfn_to_page(pfn); set_page_links(page,zone,nid,pfn); init_page_count(page); reset_page_mapcount(page); SetPageReserved(page); INIT_LIST_HEAD(&page->lru); } } 在上述函数中,由于zone参数为0,故而实际只有 SetPageReserved(page) 这行语句起作用,将flags成员设置为0x400(PG_reserved)。 下面是几个对PAGE进行操作的宏: 1.1.1.1.1 virt_to_pfn 这个宏位于include/asm/page.h中: #definevirt_to_pfn(kaddr)(__pa(kaddr)>>PAGE_SHIFT) #define__pa(vaddr)virt_to_phys((void*)(vaddr)) #definevirt_to_phys(vaddr)((unsignedlong)(vaddr)) 从这三个宏的定义可以看出,virt_to_pfn这个宏接受一个物理地址做为参数,并计算这个物理地址页在整个页表中的序号。 1.1.1.1.2 page_to_virt 这个宏位于include/asm/page.h中: #definepage_to_virt(page)((((page)-mem_map)< 在这里mem_map指向page数组的第一个元素。 这块内存空间在alloc_node_mem_map函数中使用bootmem分配。 在这里有 #definePAGE_SHIFT12 而PAGE_OFFSET的值则为0。 在上述分析可以看出,这个宏接受一个page结构体指针做为参数,并计算得到这个page结构体所代表的物理内存页的地址。 1.1.1.1.3 page_to_pfn 这个宏位于include/asm/page.h中: #definepage_to_pfn(page)virt_to_pfn(page_to_virt(page)) 根据virt_to_pfn和page_to_virt这两个宏定义可知,page_to_pfn这个宏接一个page结构体的指针做为参数,并取得这个页在整个页表中的序号。 其实在这里用 #definepage_to_pfn(page)(page–mem_map) 也可以达到相同的目的。 1.1.1.1.4 pfn_to_virt 这个宏位于include/asm/page.h中: #definepfn_to_virt(pfn)__va((pfn)< #define__va(paddr)phys_to_virt((unsignedlong)(paddr)) #definephys_to_virt(vaddr)((void*)(vaddr)) 从这三个宏定义可以看出,这个宏接受页面序号做为参数,并返回指定序号的页面的物理地址。 1.1.1.1.5 virt_to_page 内核对每一个4K的内存页都用一个page结构进行描述,使用virt_to_page这个宏定义可以快速地找到指定物理地址对应的page结构体。 这个宏位于include/asm/page.h中: #definevirt_to_page(addr)(mem_map+(((unsignedlong)(addr)-PAGE_OFFSET)>>PAGE_SHIFT)) 在这里mem_map指向page数组的第一个元素。 这块内存空间在alloc_node_mem_map函数中使用bootmem分配,但是与其它用bootmem分配的内存不同,这块内存空间永远不会被回收。 在这里有 #definePAGE_SHIFT12 而PAGE_OFFSET的值则为0。 在上述分析可以看出,这个宏接受一个物理地址做为参数,并计算得到表示这个物理地址所在页面的page结构体指针。 1.1.1.1.6 pfn_to_page 这个宏位于include/asm/page.h中: #definepfn_to_page(pfn)virt_to_page(pfn_to_virt(pfn)) 根据pfn_to_virt和virt_to_page这两个宏定义可知,pfn_to_page这个宏接受一个page序号做为参数,并取得这个序号所代表的page结构体指针。 其实在这里用 #definepfn_to_page(pfn)(page+mem_map) 也可以达到相同的目的。 1.1.1.2 zone 内核将整个存储空间划分为几个zone,每个zone都用一个zone结构体表示。 由于在BF561中只使用了ZONE_DMA这一个区域,因而可以认为内核中每次出现的zone指针都指向一个全局唯一的地址。 zone这个结构体的定义位于include/linux/mmzone.h,它实际管理着所有的内存页面链表: structzone{ /*Fieldscommonlyaccessedbythepageallocator*/ unsignedlongpages_min,pages_low,pages_high; /* *Wedon'tknowifthememorythatwe'regoingtoallocatewillbefreeable *or/anditwillbereleasedeventually,sotoavoidtotallywastingseveral *GBoframwemustreservesomeofthelowerzonememory(otherwisewerisk *torunOOMonthelowerzonesdespitethere'stonsoffreeableram *onthehigherzones).Thisarrayisrecalculatedatruntimeifthe *sysctl_lowmem_reserve_ratiosysctlchanges. */ unsignedlonglowmem_reserve[MAX_NR_ZONES]; structper_cpu_pagesetpageset[NR_CPUS]; /* *freeareasofdifferentsizes */ spinlock_tlock; structfree_areafree_area[MAX_ORDER]; ZONE_PADDING(_pad1_) /*Fieldscommonlyaccessedbythepage
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- linux page