linux如何管理物理内存?

Posted Jello

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux如何管理物理内存?相关的知识,希望对你有一定的参考价值。

Linux kernel version: 5.0.1

arm64

  1.将物理内存划分为若干页,每页的大小为4KiB(可以为8KiB或16KiB),那么如何知道每个页当前是什么情况呢?

  那就需要一个结构体来描述每一页的情况,那么就出现了结构体struct page.

  2.有若干页,意味着需要若干个struct page这样的结构体来描述若干页的状态;

  3.这些struct page存放在哪里呢?肯定是存放在物理内存里;

  4.存放在物理内存里,那么假设物理内存有4MiB,指定页面大小为4KiB,那么这些物理内存能被划分为多少个页面呢?又需要多少物理内存来存放struct page结构体呢?

  页面个数=4MiB/4KiB=4*1024 KiB/4KiB=1024个;

  那么就需要1024个struct page来描述这1024个页面的情况,这么多结构体需要多少内存呢?

  1024 * sizeof(struct page)

  5.如何获取sizeof(struct page)的大小呢?

  struct page结构体(结构体定义在include/linux/mm_types.h)如下:

技术图片
  1   struct page {
  2       unsigned long flags;        /* Atomic flags, some possibly
  3                        * updated asynchronously */
  4       /*
  5        * Five words (20/40 bytes) are available in this union.
  6        * WARNING: bit 0 of the first word is used for PageTail(). That
  7        * means the other users of this union MUST NOT use the bit to
  8        * avoid collision and false-positive PageTail().
  9        */
 10       union {
 11           struct {    /* Page cache and anonymous pages */
 12               /**
 13                * @lru: Pageout list, eg. active_list protected by
 14                * zone_lru_lock.  Sometimes used as a generic list
 15                * by the page owner.
 16                */
 17               struct list_head lru;
 18               /* See page-flags.h for PAGE_MAPPING_FLAGS */
 19               struct address_space *mapping;
 20               pgoff_t index;      /* Our offset within mapping. */
 21               /**
 22                * @private: Mapping-private opaque data.
 23                * Usually used for buffer_heads if PagePrivate.
 24                * Used for swp_entry_t if PageSwapCache.
 25                * Indicates order in the buddy system if PageBuddy.
 26                */
 27               unsigned long private;
 28           };
 29           struct {    /* slab, slob and slub */
 30               union {
 31                   struct list_head slab_list; /* uses lru */
 32                   struct {    /* Partial pages */
 33                       struct page *next;
 34   #ifdef CONFIG_64BIT
 35                       int pages;  /* Nr of pages left */
 36                       int pobjects;   /* Approximate count */
 37   #else
 38                       short int pages;
 39                       short int pobjects;
 40   #endif
 41                   };
 42               };
 43               struct kmem_cache *slab_cache; /* not slob */
 44               /* Double-word boundary */
 45               void *freelist;     /* first free object */
 46               union {
 47                   void *s_mem;    /* slab: first object */
 48                   unsigned long counters;     /* SLUB */
 49                   struct {            /* SLUB */
 50                       unsigned inuse:16;
 51                       unsigned objects:15;
 52                       unsigned frozen:1;
 53                   };
 54               };
 55           };
 56           struct {    /* Tail pages of compound page */
 57               unsigned long compound_head;    /* Bit zero is set */
 58 
 59               /* First tail page only */
 60               unsigned char compound_dtor;
 61               unsigned char compound_order;
 62               atomic_t compound_mapcount;
 63           };
 64           struct {    /* Second tail page of compound page */
 65               unsigned long _compound_pad_1;  /* compound_head */
 66               unsigned long _compound_pad_2;
 67               struct list_head deferred_list;
 68           };
 69           struct {    /* Page table pages */
 70               unsigned long _pt_pad_1;    /* compound_head */
 71               pgtable_t pmd_huge_pte; /* protected by page->ptl */
 72               unsigned long _pt_pad_2;    /* mapping */
 73               union {
 74                   struct mm_struct *pt_mm; /* x86 pgds only */
 75                   atomic_t pt_frag_refcount; /* powerpc */
 76               };
 77   #if ALLOC_SPLIT_PTLOCKS
 78               spinlock_t *ptl;
 79   #else
 80               spinlock_t ptl;
 81   #endif
 82           };
 83           struct {    /* ZONE_DEVICE pages */
 84               /** @pgmap: Points to the hosting device page map. */
 85               struct dev_pagemap *pgmap;
 86               unsigned long hmm_data;
 87               unsigned long _zd_pad_1;    /* uses mapping */
 88           };
 89 
 90           /** @rcu_head: You can use this to free a page by RCU. */
 91           struct rcu_head rcu_head;
 92       };
 93 
 94       union {     /* This union is 4 bytes in size. */
 95           /*
 96            * If the page can be mapped to userspace, encodes the number
 97            * of times this page is referenced by a page table.
 98            */
 99           atomic_t _mapcount;
100 
101           /*
102            * If the page is neither PageSlab nor mappable to userspace,
103            * the value stored here may help determine what this page
104            * is used for.  See page-flags.h for a list of page types
105            * which are currently stored here.
106            */
107           unsigned int page_type;
108 
109           unsigned int active;        /* SLAB */
110           int units;          /* SLOB */
111       };
112 
113       /* Usage count. *DO NOT USE DIRECTLY*. See page_ref.h */
114       atomic_t _refcount;
115 
116   #ifdef CONFIG_MEMCG
117       struct mem_cgroup *mem_cgroup;
118   #endif
119 
120       /*
121        * On machines where all RAM is mapped into kernel address space,
122        * we can simply calculate the virtual address. On machines with
123        * highmem some memory is mapped into kernel virtual memory
124        * dynamically, so we need a place to store that address.
125        * Note that this field could be 16 bits on x86 ... ;)
126        *
127        * Architectures with slow multiplication can define
128        * WANT_PAGE_VIRTUAL in asm/page.h
129        */
130   #if defined(WANT_PAGE_VIRTUAL)
131       void *virtual;          /* Kernel virtual address (NULL if
132                          not kmapped, ie. highmem) */
133   #endif /* WANT_PAGE_VIRTUAL */
134 
135   #ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS
136       int _last_cpupid;
137   #endif
138   } _struct_page_alignment;
View Code

  使用此内核模块获取,编译方法为:make CROSS_COMPILE=1 KDIR=<linux kernel source code path>

  所以:

  1024 * sizeof(struct page) = 1024 * 64 = 64 KiB = 16 个页面

  6.既然有部分物理内存用来存储每个页面的情况,那么可用的物理内存必然少于4MiB,那么具体是多少呢?

  1024 - 16 = 1008 个页面 = 1008 * 4 KiB = 4032 KiB

  

以上是关于linux如何管理物理内存?的主要内容,如果未能解决你的问题,请参考以下文章

linux如何管理物理内存?

一文掌握 Linux 内存管理

Linux 内核 内存管理物理分配页 ⑨ ( __alloc_pages_slowpath 慢速路径调用函数源码分析 | retry 标号代码分析 )

linux内存池能分配连续物理内存吗

linux内存管理--linux内核高端内存

linux 下如何查看服务器物理内存状况