[关闭]
@ljm 2016-08-25T18:59:56.000000Z 字数 4678 阅读 4342

struct page的解析

内存管理


struct page是内存管理中重要的数据结构,它代表系统内存的最小单位。
其数据结构如下所示:

  1. /*
  2. * Each physical page in the system has a struct page associated with
  3. * it to keep track of whatever it is we are using the page for at the
  4. * moment. Note that we have no way to track which tasks are using
  5. * a page, though if it is a pagecache page, rmap structures can tell us
  6. * who is mapping it.
  7. *
  8. * The objects in struct page are organized in double word blocks in
  9. * order to allows us to use atomic double word operations on portions
  10. * of struct page. That is currently only used by slub but the arrangement
  11. * allows the use of atomic double word operations on the flags/mapping
  12. * and lru list pointers also.
  13. */
  14. struct page {
  15. /* First double word block */
  16. unsigned long flags; /* Atomic flags, some possibly
  17. * updated asynchronously */
  18. union {
  19. struct address_space *mapping; /* If low bit clear, points to
  20. * inode address_space, or NULL.
  21. * If page mapped as anonymous
  22. * memory, low bit is set, and
  23. * it points to anon_vma object:
  24. * see PAGE_MAPPING_ANON below.
  25. */
  26. void *s_mem; /* slab first object */
  27. atomic_t compound_mapcount; /* first tail page */
  28. /* page_deferred_list().next -- second tail page */
  29. };
  30. /* Second double word */
  31. struct {
  32. union {
  33. pgoff_t index; /* Our offset within mapping. */
  34. void *freelist; /* sl[aou]b first free object */
  35. /* page_deferred_list().prev -- second tail page */
  36. };
  37. union {
  38. #if defined(CONFIG_HAVE_CMPXCHG_DOUBLE) && \
  39. defined(CONFIG_HAVE_ALIGNED_STRUCT_PAGE)
  40. /* Used for cmpxchg_double in slub */
  41. unsigned long counters;
  42. #else
  43. /*
  44. * Keep _count separate from slub cmpxchg_double data.
  45. * As the rest of the double word is protected by
  46. * slab_lock but _count is not.
  47. */
  48. unsigned counters;
  49. #endif
  50. struct {
  51. union {
  52. /*
  53. * Count of ptes mapped in mms, to show
  54. * when page is mapped & limit reverse
  55. * map searches.
  56. */
  57. atomic_t _mapcount;
  58. struct { /* SLUB */
  59. unsigned inuse:16;
  60. unsigned objects:15;
  61. unsigned frozen:1;
  62. };
  63. int units; /* SLOB */
  64. };
  65. atomic_t _count; /* Usage count, see below. */
  66. };
  67. unsigned int active; /* SLAB */
  68. };
  69. };
  70. /*
  71. * Third double word block
  72. *
  73. * WARNING: bit 0 of the first word encode PageTail(). That means
  74. * the rest users of the storage space MUST NOT use the bit to
  75. * avoid collision and false-positive PageTail().
  76. */
  77. union {
  78. struct list_head lru; /* Pageout list, eg. active_list
  79. * protected by zone->lru_lock !
  80. * Can be used as a generic list
  81. * by the page owner.
  82. */
  83. struct dev_pagemap *pgmap; /* ZONE_DEVICE pages are never on an
  84. * lru or handled by a slab
  85. * allocator, this points to the
  86. * hosting device page map.
  87. */
  88. struct { /* slub per cpu partial pages */
  89. struct page *next; /* Next partial slab */
  90. #ifdef CONFIG_64BIT
  91. int pages; /* Nr of partial slabs left */
  92. int pobjects; /* Approximate # of objects */
  93. #else
  94. short int pages;
  95. short int pobjects;
  96. #endif
  97. };
  98. struct rcu_head rcu_head; /* Used by SLAB
  99. * when destroying via RCU
  100. */
  101. /* Tail pages of compound page */
  102. struct {
  103. unsigned long compound_head; /* If bit zero is set */
  104. /* First tail page only */
  105. #ifdef CONFIG_64BIT
  106. /*
  107. * On 64 bit system we have enough space in struct page
  108. * to encode compound_dtor and compound_order with
  109. * unsigned int. It can help compiler generate better or
  110. * smaller code on some archtectures.
  111. */
  112. unsigned int compound_dtor;
  113. unsigned int compound_order;
  114. #else
  115. unsigned short int compound_dtor;
  116. unsigned short int compound_order;
  117. #endif
  118. };
  119. #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && USE_SPLIT_PMD_PTLOCKS
  120. struct {
  121. unsigned long __pad; /* do not overlay pmd_huge_pte
  122. * with compound_head to avoid
  123. * possible bit 0 collision.
  124. */
  125. pgtable_t pmd_huge_pte; /* protected by page->ptl */
  126. };
  127. #endif
  128. };
  129. /* Remainder is not double word aligned */
  130. union {
  131. unsigned long private; /* Mapping-private opaque data:
  132. * usually used for buffer_heads
  133. * if PagePrivate set; used for
  134. * swp_entry_t if PageSwapCache;
  135. * indicates order in the buddy
  136. * system if PG_buddy is set.
  137. */
  138. #if USE_SPLIT_PTE_PTLOCKS
  139. #if ALLOC_SPLIT_PTLOCKS
  140. spinlock_t *ptl;
  141. #else
  142. spinlock_t ptl;
  143. #endif
  144. #endif
  145. struct kmem_cache *slab_cache; /* SL[AU]B: Pointer to slab */
  146. };
  147. #ifdef CONFIG_MEMCG
  148. struct mem_cgroup *mem_cgroup;
  149. #endif
  150. /*
  151. * On machines where all RAM is mapped into kernel address space,
  152. * we can simply calculate the virtual address. On machines with
  153. * highmem some memory is mapped into kernel virtual memory
  154. * dynamically, so we need a place to store that address.
  155. * Note that this field could be 16 bits on x86 ... ;)
  156. *
  157. * Architectures with slow multiplication can define
  158. * WANT_PAGE_VIRTUAL in asm/page.h
  159. */
  160. #if defined(WANT_PAGE_VIRTUAL)
  161. void *virtual; /* Kernel virtual address (NULL if
  162. not kmapped, ie. highmem) */
  163. #endif /* WANT_PAGE_VIRTUAL */
  164. #ifdef CONFIG_KMEMCHECK
  165. /*
  166. * kmemcheck wants to track the status of each byte in a page; this
  167. * is a pointer to such a status block. NULL if not tracked.
  168. */
  169. void *shadow;
  170. #endif
  171. #ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS
  172. int _last_cpupid;
  173. #endif
  174. }

因为内核会为每一个物理页帧创建一个struct page的结构体,因此要保证page结构体足够的小,否则仅struct page就要占用大量的内存。出于节省内存的考虑,struct page中使用了大量的联合体union。下面仅对常用的一些的字段做说明:

注意区分_count和_mapcount,_mapcount表示的是映射次数,而_count表示的是使用次数;被映射了不一定在使用,但要使用必须先映射。


参考资料:
1. chinaunix 夕阳下的孤影

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注