上次介绍了物理内存管理中三位主要人物中的node 和zone。这两位是当官的,一个是县长,一个是里长,不敢不先介绍啊。接下来出场的就是我们的老百姓了 --- page frame。
Page frame是物理内存的基本组成单位,在Kernel中由结构体 struct page 来描述。
struct page {unsigned long flags;atomic_t _count;union {atomic_t _mapcount;unsigned int inuse;};union {struct {unsigned long private;struct address_space *mapping; };struct kmem_cache *slab; /* SLUB: Pointer to slab */struct page *first_page; /* Compound tail pages */};union {pgoff_t index; /* Our offset within mapping. */void *freelist; /* SLUB: freelist req. slab lock */};struct list_head lru;
};
这个结构体是不是长得很有特色?它里面的'union'特别多。
在中国,有好多大家不喜欢的制度,归根到底就一个原因 --- 人多。所以才有了户口制度来限制城市人口,所以才会采用高考制度来筛选人才。。。
在内存管理中,我们也面临着相同的问题 --- 内存页太多。假设我们有1G内存,采用4K的分页,则会有262144 (26万)个内存页,相应的就需要26万个struct page结构体。如果该结构体的大小增加一点点,放大26万倍,增加的内存消耗就很可观了。
为此,Kernel是绞尽了脑汁来减少该结构体的大小。毕竟全国百姓那么多,每个人多分配点田地,那整体的田地消耗太大。不像县长或里长这些当官的,数量有限,每个人多贪污点也影响不大。
Kernel采取的措施就是尽可能地重用同一个成员变量。房子大小有限,只能是白天当书房,晚上当卧室。
这就是为啥这个结构体中大量的使用了union。
flags: 用来描述page frame的属性或状态。
_count:这个没啥好说的,使用计数器。
_mapcount:也是个计数器,不过这里只是统计页表中有多少页表项指向该page frame。
inuse, slab, freelist:由slub使用,暂且略去不讲。
private:这个。。不同的使用场景下表示的含义也不同。为了节省空间而重用成员变量的另一种形式。是攻还是受,得看遇到了谁。
mapping:这个也是个多重人格,攻受兼备的主。一般会和 index 配合,表示在page cache中该page frame属于哪个address space。以后会详细讲到。
first_page: 在compound page中指向带头大哥。
lru: 还记不记得在结构体zone中有两个链表:active_list, inactive_list。嗯,lru就是干这个用的。
百闻不如一见。我们拿一个具体的例子,看看这三位人物的主要属性是怎么赋值的。
该实例中物理内存被分为两个node。
struct pglist_data {node_zones = ffff810000008101,node_zonelists = ffff81000000ad01,nr_zones = 3,node_mem_map = 0xffff8117df000000,node_start_pfn = 0,node_present_pages = 25162223,node_spanned_pages = 25427968,node_id = 0,kswapd_wait = ffff81000000d619,kswapd = 0xffff8117a27e3300,kswapd_max_order = 0
}
struct pglist_data {node_zones = ffff811840000000,node_zonelists = ffff811840002c00,nr_zones = 3,node_mem_map = 0xffff812fe0000000,node_start_pfn = 25427968,node_present_pages = 25165824,node_spanned_pages = 25165824,node_id = 1,kswapd_wait = ffff811840005518,kswapd = 0xffff8117a27e3300,kswapd_max_order = 0
}
我们以第一个Node为例,它被分成了三个zones:DMA, DMA32 and Normal。
node_zones = {{pages_min = 0,pages_low = 0,pages_high = 0,lowmem_reserve = {0, 2978, 96722, 96722},node = 0,free_area =active_list = {next = 0xffff810000008a91,prev = 0xffff810000008a91},inactive_list = {next = 0xffff810000008aa1,prev = 0xffff810000008aa1},nr_scan_active = 0,nr_scan_inactive = 0,pages_scanned = 0,prev_priority = 12,wait_table = 0xffff810000001000,wait_table_hash_nr_entries = 16,wait_table_bits = 4,zone_pgdat = 0xffff810000008101,zone_start_pfn = 0,spanned_pages = 4096,present_pages = 1233,name = 0xffffffff8058c55c "DMA"}, {pages_min = 216,pages_low = 270,pages_high = 324,lowmem_reserve = {0, 0, 93744, 93744},node = 0,free_area = active_list = {next = 0xffff810000009591,prev = 0xffff810000009591},inactive_list = {next = 0xffff8100000095a1,prev = 0xffff8100000095a1},nr_scan_active = 0,nr_scan_inactive = 0,pages_scanned = 0,prev_priority = 12,wait_table = 0xffff810001000000,wait_table_hash_nr_entries = 4096,wait_table_bits = 12,zone_pgdat = 0xffff810000008101,zone_start_pfn = 4096,spanned_pages = 1044480,present_pages = 762517,name = 0xffffffff8056824d "DMA32"}, {pages_min = 6819,pages_low = 8523,pages_high = 10228,lowmem_reserve = {0, 0, 0, 0},node = 0,free_area =active_list = {next = 0xffff81180da37e68,prev = 0xffff81183d80b528},inactive_list = {next = 0xffff81180f4e6be8,prev = 0xffff81183d823b68},nr_scan_active = 0,nr_scan_inactive = 0,pages_scanned = 0,prev_priority = 12,wait_table = 0xffff810001020000,wait_table_hash_nr_entries = 4096,wait_table_bits = 12,zone_pgdat = 0xffff810000008101,zone_start_pfn = 1048576,spanned_pages = 24379392,present_pages = 23998464,name = 0xffffffff80568253 "Normal"
}
至此物理内存管理中三位主要人物就介绍完了。他们之间都有些什么恩怨情仇血雨腥风的故事呢?敬请期待!
转载于:https://blog.51cto.com/richardguo/1663808