struct page { unsigned long flags; /* Atomic flags, some possibly * updated asynchronously */ atomic_t _count; /* Usage count, see below. */ union { atomic_t _mapcount; /* Count of ptes mapped in mms, * to show when page is mapped * & limit reverse map searches. */ struct { /* SLUB */ u16 inuse; u16 objects; }; }; union { struct { unsigned long private; /* Mapping-private opaque data: * usually used for buffer_heads * if PagePrivate set; used for * swp_entry_t if PageSwapCache; * indicates order in the buddy * system if PG_buddy is set. */ struct address_space *mapping; /* If low bit clear, points to * inode address_space, or NULL. * If page mapped as anonymous * memory, low bit is set, and * it points to anon_vma object: * see PAGE_MAPPING_ANON below. */ }; #if USE_SPLIT_PTLOCKS spinlock_t ptl; #endif 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; /* Pageout list, eg. active_list * protected by zone->lru_lock ! */ /* * On machines where all RAM is mapped into kernel address space, * we can simply calculate the virtual address. On machines with * highmem some memory is mapped into kernel virtual memory * dynamically, so we need a place to store that address. * Note that this field could be 16 bits on x86 ... ;) * * Architectures with slow multiplication can define * WANT_PAGE_VIRTUAL in asm/page.h */ #if defined(WANT_PAGE_VIRTUAL) void *virtual; /* Kernel virtual address (NULL if not kmapped, ie. highmem) */ #endif /* WANT_PAGE_VIRTUAL */ #ifdef CONFIG_WANT_PAGE_DEBUG_FLAGS unsigned long debug_flags; /* Use atomic bitops on this */ #endif #ifdef CONFIG_KMEMCHECK /* * kmemcheck wants to track the status of each byte in a page; this * is a pointer to such a status block. NULL if not tracked. */ void *shadow; #endif }; /* * A region containing a mapping of a non-memory backed file under NOMMU * conditions. These are held in a global tree and are pinned by the VMAs that * map parts of them. */ struct vm_region { struct rb_node vm_rb; /* link in global region tree */ unsigned long vm_flags; /* VMA vm_flags */ unsigned long vm_start; /* start address of region */ unsigned long vm_end; /* region initialised to here */ unsigned long vm_top; /* region allocated to here */ unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */ struct file *vm_file; /* the backing file or NULL */ int vm_usage; /* region usage count (access under nommu_region_sem) */ bool vm_icache_flushed : 1; /* true if the icache has been flushed for * this region */ };
1 unsigned long flags
unsigned long flags //flags在page-flags.h文件夾中枚舉 //paging_init()可設置PG_reserved做flags //mem_init()可設置含PG_reserved的flags清除 //#define PG_reserved 11;表示頁保留,無法被__free_page()回收
2 atomic_t _count和atumic_t _mapcount
atomic_t _count; //頁引用計數器 atomic_t _mapcount; //頁映射計數器 //paging_init()可以將它們初始化為-1 //mem_init()可以將所有位碼為0的頁的_count設置為0 //page_count和page_mapcount可以統計其實用者個數 //_count+1為頁使用者個數,_mapcount+1為頁共享者個數 // _count為-1時不可被__free_page()釋放 //_mapcount為0表示該頁未被共享
3 unsigned long private
unsigned long private; //私有數據指針 //設置為PG_private,則private字段指向struct buffer_head //設置為PG_compound,則指向struct page //設置為PG_swapcache,則private為swp_entry_t的成員變量val
4 struct address_space *mapping
struct address_space *mapping; //該頁所在地址空間描述結構指針 /*page->mapping == 0 屬於交換高速緩存頁 *page->mapping != 0 且第0位為1,為匿名頁,指向struct anon_vma *page->mapping != 0 且第0位為0,指向struct address_space地址空間結構變量 */
5 pgoff_t index
pgoff_t index; //該頁描述結構在地址空間radix樹page_tree中的對象索引號即頁號 //表示該頁在vm_file中的便宜頁數 //#define unsigned long pgoff_t
6 struct list_head lru
struct list_head lru; //最近、最久未使用struct slab結構指針變量 //設置PG_slab,則該頁由slab分配器來管理,lru.next指向kmem_cache_t結構變量,lru.prev則指向struct slab結構
7 struct pagevec
struct pagevec { //頁向量描述結構 unsigned long nr; //該頁向量中的內存頁數 unsigned long cold; //冷區標志,0表示熱區,非0表示冷區 struct page *pages[PAGEVEC_SIZE]; //該也想兩種的頁描述結構指針數組(PAGEVEC_SIZE=14) };
8 struct page_address_map
struct page_address_map { //頁地址映射 struct page *page; //頁的描述結構 void *virtual; //頁的虛擬地址 struct list_head list; //通過list字段鏈接到頁表池全局鏈表page_address_pool中或page_address_htable[hash_ptr(page,PA_HASH_ORDER)].lh };
9 struct page_address_slot
static struct page_address_slot { struct list_head lh; /* List of page_address_maps */ spinlock_t lock; /* Protect this bucket's list */ } ____cacheline_aligned_in_smp page_address_htable[1<<PA_HASH_ORDER];