ページ記述子は物理ページと関連したオブジェクトです。
カーネル側としてはページ記述子が物理ページ・物理アドレスの情報を持っていてくれることで、システムにあるページの情報を把握することができます。
例えばページが未使用(未割り当て)なのか、使用中(割り当て済み)ならば誰が所有者なのかという情報も含まれます。
所有者については必ずしもユーザープロセスに限定されず、以下のようなケースもありえますね。
ではコードも見てみましょう。
ページ記述子は構造体としては複雑な方に部類されるかと…
まあ、とりあえず宣言・定義を見ちゃってくださいな。
// /usr/src/linux-headers-4.18.16-041816-generic/include/linux/mm_types.h 70 struct page { 71 unsigned long flags; /* Atomic flags, some possibly 72 * updated asynchronously */ 73 /* 74 * Five words (20/40 bytes) are available in this union. 75 * WARNING: bit 0 of the first word is used for PageTail(). That 76 * means the other users of this union MUST NOT use the bit to 77 * avoid collision and false-positive PageTail(). 78 */ 79 union { 80 struct { /* Page cache and anonymous pages */ 81 /** 82 * @lru: Pageout list, eg. active_list protected by 83 * zone_lru_lock. Sometimes used as a generic list 84 * by the page owner. 85 */ 86 struct list_head lru; 87 /* See page-flags.h for PAGE_MAPPING_FLAGS */ 88 struct address_space *mapping; 89 pgoff_t index; /* Our offset within mapping. */ 90 /** 91 * @private: Mapping-private opaque data. 92 * Usually used for buffer_heads if PagePrivate. 93 * Used for swp_entry_t if PageSwapCache. 94 * Indicates order in the buddy system if PageBuddy. 95 */ 96 unsigned long private; 97 }; 98 struct { /* slab, slob and slub */ 99 union { 100 struct list_head slab_list; /* uses lru */ 101 struct { /* Partial pages */ 102 struct page *next; 103 #ifdef CONFIG_64BIT 104 int pages; /* Nr of pages left */ 105 int pobjects; /* Approximate count */ 106 #else 107 short int pages; 108 short int pobjects; 109 #endif 110 }; 111 }; 112 struct kmem_cache *slab_cache; /* not slob */ 113 /* Double-word boundary */ 114 void *freelist; /* first free object */ 115 union { 116 void *s_mem; /* slab: first object */ 117 unsigned long counters; /* SLUB */ 118 struct { /* SLUB */ 119 unsigned inuse:16; 120 unsigned objects:15; 121 unsigned frozen:1; 122 }; 123 }; 124 }; 125 struct { /* Tail pages of compound page */ 126 unsigned long compound_head; /* Bit zero is set */ 127 128 /* First tail page only */ 129 unsigned char compound_dtor; 130 unsigned char compound_order; 131 atomic_t compound_mapcount; 132 }; 133 struct { /* Second tail page of compound page */ 134 unsigned long _compound_pad_1; /* compound_head */ 135 unsigned long _compound_pad_2; 136 struct list_head deferred_list; 137 }; 138 struct { /* Page table pages */ 139 unsigned long _pt_pad_1; /* compound_head */ 140 pgtable_t pmd_huge_pte; /* protected by page->ptl */ 141 unsigned long _pt_pad_2; /* mapping */ 142 union { 143 struct mm_struct *pt_mm; /* x86 pgds only */ 144 atomic_t pt_frag_refcount; /* powerpc */ 145 }; 146 #if ALLOC_SPLIT_PTLOCKS 147 spinlock_t *ptl; 148 #else 149 spinlock_t ptl; 150 #endif 151 }; 152 struct { /* ZONE_DEVICE pages */ 153 /** @pgmap: Points to the hosting device page map. */ 154 struct dev_pagemap *pgmap; 155 unsigned long hmm_data; 156 unsigned long _zd_pad_1; /* uses mapping */ 157 }; 158 159 /** @rcu_head: You can use this to free a page by RCU. */ 160 struct rcu_head rcu_head; 161 }; 162 163 union { /* This union is 4 bytes in size. */ 164 /* 165 * If the page can be mapped to userspace, encodes the number 166 * of times this page is referenced by a page table. 167 */ 168 atomic_t _mapcount; 169 170 /* 171 * If the page is neither PageSlab nor mappable to userspace, 172 * the value stored here may help determine what this page 173 * is used for. See page-flags.h for a list of page types 174 * which are currently stored here. 175 */ 176 unsigned int page_type; 177 178 unsigned int active; /* SLAB */ 179 int units; /* SLOB */ 180 }; 181 182 /* Usage count. *DO NOT USE DIRECTLY*. See page_ref.h */ 183 atomic_t _refcount; 184 185 #ifdef CONFIG_MEMCG 186 struct mem_cgroup *mem_cgroup; 187 #endif 188 189 /* 190 * On machines where all RAM is mapped into kernel address space, 191 * we can simply calculate the virtual address. On machines with 192 * highmem some memory is mapped into kernel virtual memory 193 * dynamically, so we need a place to store that address. 194 * Note that this field could be 16 bits on x86 ... ;) 195 * 196 * Architectures with slow multiplication can define 197 * WANT_PAGE_VIRTUAL in asm/page.h 198 */ 199 #if defined(WANT_PAGE_VIRTUAL) 200 void *virtual; /* Kernel virtual address (NULL if 201 not kmapped, ie. highmem) */ 202 #endif /* WANT_PAGE_VIRTUAL */ 203 204 #ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS 205 int _last_cpupid; 206 #endif 207 } _struct_page_alignment;
この中で特に重要なメンバー変数は flags です。
flags はページが dirty かロック状態か等の情報を保持します。
まあ dirty が何かどかロックどかは重要じゃないんで覚える必要は無いです。
それと _refcount はページへの参照の数をキープしてくれます。
virtual はページの仮想アドレスを保持します。
まあ、こんなもんですかね。
Copyright 2018-2019, by Masaki Komatsu