内存学习

Free_area是一个数组用做buddy系统,每一个数组代表固定大小的连续内存

 

struct free_area {

   struct list_head  free_list[MIGRATE_TYPES];

   unsigned long     nr_free;

};

如果一个页经常被用到可以看成是active的,inactive页则相反。在页面换出时active页会被尽可能的换出刷到磁盘上

active_list收集active inactive_list收集 inactive

nr_scan_active nr_scan_inactive用于内存恢复时扫描有多少 active inactive

pages_scanned记录上一次页交换有多少页没被扫描到

flag 描述现在zone区域的状态

typedef enum {

   ZONE_ALL_UNRECLAIMABLE,     /* all pages pinned */

   ZONE_RECLAIM_LOCKED,   /* prevents concurrent reclaim */

   ZONE_OOM_LOCKED,    /* zone is in OOM killer zonelist */

} zone_flags_t;

内核使用三个函数测试和设置flag

void zone_set_flag(struct zone *zone, zone_flags_t flag)

int zone_test_and_set_flag(struct zone *zone, zone_flags_t flag)

void zone_clear_flag(struct zone *zone, zone_flags_t flag)

static inline void zone_set_flag(struct zone *zone, zone_flags_t flag)

{

   set_bit(flag, &zone->flags);

}

zone_page_state用于记录zone信息

static inline unsigned long zone_page_state(struct zone *zone,

             enum zone_stat_item item)

{

   long x = atomic_long_read(&zone->vm_stat[item]);

#ifdef CONFIG_SMP

   if (x < 0)

     x = 0;

#endif

   return x;

}

144

min_free_kbytes表示内核最低空闲内存值

 

min_free_kbytes = sqrt(lowmem_kbytes * 16)

通常初始化值是1024K1M

* 16MB: 512k

 * 32MB:  724k

 * 64MB:  1024k

 * 128MB: 1448k

 * 256MB: 2048k

 * 512MB: 2896k

 * 1024MB: 4096k

 * 2048MB: 5792k

 * 4096MB: 8192k

 * 8192MB: 11584k

 * 16384MB:  16384k

cat /proc/sys/vm/min_free_kbytes 可以看到

struct zone {

   /* Fields commonly accessed by the page allocator */

   unsigned long     pages_min, pages_low, pages_high;

   /*

    * We don't know if the memory that we're going to allocate will be freeable

    * or/and it will be released eventually, so to avoid totally wasting several

    * GB of ram we must reserve some of the lower zone memory (otherwise we risk

    * to run OOM on the lower zones despite there's tons of freeable ram

    * on the higher zones). This array is recalculated at runtime if the

    * sysctl_lowmem_reserve_ratio sysctl changes.

    */

   unsigned long     lowmem_reserve[MAX_NR_ZONES];

 

#ifdef CONFIG_NUMA

   int node;

   /*

    * zone reclaim becomes active if more unmapped pages exist.

    */

   unsigned long     min_unmapped_pages;

   unsigned long     min_slab_pages;

   struct per_cpu_pageset *pageset[NR_CPUS];

#else

   struct per_cpu_pageset pageset[NR_CPUS];

#endif

   /*

    * free areas of different sizes

    */

   spinlock_t   lock;

#ifdef CONFIG_MEMORY_HOTPLUG

   /* see spanned/present_pages for more description */

   seqlock_t    span_seqlock;

#endif

   struct free_area  free_area[MAX_ORDER];

 

#ifndef CONFIG_SPARSEMEM

   /*

    * Flags for a pageblock_nr_pages block. See pageblock-flags.h.

    * In SPARSEMEM, this map is stored in struct mem_section

    */

   unsigned long     *pageblock_flags;

#endif /* CONFIG_SPARSEMEM */

 

 

   ZONE_PADDING(_pad1_)

 

   /* Fields commonly accessed by the page reclaim scanner */

   spinlock_t   lru_lock;

   struct {

     struct list_head list;

     unsigned long nr_scan;

   } lru[NR_LRU_LISTS];

 

   struct zone_reclaim_stat reclaim_stat;

 

   unsigned long     pages_scanned;    /* since last reclaim */

   unsigned long     flags;       /* zone flags, see below */

 

   /* Zone statistics */

   atomic_long_t     vm_stat[NR_VM_ZONE_STAT_ITEMS];

 

   /*

    * prev_priority holds the scanning priority for this zone.  It is

    * defined as the scanning priority at which we achieved our reclaim

    * target at the previous try_to_free_pages() or balance_pgdat()

    * invokation.

    *

    * We use prev_priority as a measure of how much stress page reclaim is

    * under - it drives the swappiness decision: whether to unmap mapped

    * pages.

    *

    * Access to both this field is quite racy even on uniprocessor.  But

    * it is expected to average out OK.

    */

   int prev_priority;

 

   /*

    * The target ratio of ACTIVE_ANON to INACTIVE_ANON pages on

    * this zone's LRU.  Maintained by the pageout code.

    */

   unsigned int inactive_ratio;

 

 

   ZONE_PADDING(_pad2_)

   /* Rarely used or read-mostly fields */

 

   /*

    * wait_table     -- the array holding the hash table

    * wait_table_hash_nr_entries  -- the size of the hash table array

    * wait_table_bits  -- wait_table_size == (1 << wait_table_bits)

    *

    * The purpose of all these is to keep track of the people

    * waiting for a page to become available and make them

    * runnable again when possible. The trouble is that this

    * consumes a lot of space, especially when so few things

    * wait on pages at a given time. So instead of using

    * per-page waitqueues, we use a waitqueue hash table.

    *

    * The bucket discipline is to sleep on the same queue when

    * colliding and wake all in that wait queue when removing.

    * When something wakes, it must check to be sure its page is

    * truly available, a la thundering herd. The cost of a

    * collision is great, but given the expected load of the

    * table, they should be so rare as to be outweighed by the

    * benefits from the saved space.

    *

    * __wait_on_page_locked() and unlock_page() in mm/filemap.c, are the

    * primary users of these fields, and in mm/page_alloc.c

    * free_area_init_core() performs the initialization of them.

    */

   wait_queue_head_t * wait_table;

   unsigned long     wait_table_hash_nr_entries;

   unsigned long     wait_table_bits;

 

   /*

    * Discontig memory support fields.

    */

   struct pglist_data  *zone_pgdat;

   /* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */

   unsigned long     zone_start_pfn;

 

   /*

    * zone_start_pfn, spanned_pages and present_pages are all

    * protected by span_seqlock.  It is a seqlock because it has

    * to be read outside of zone->lock, and it is done in the main

    * allocator path.  But, it is written quite infrequently.

    *

    * The lock is declared along with zone->lock because it is

    * frequently read in proximity to zone->lock.  It's good to

    * give them a chance of being in the same cacheline.

    */

   unsigned long     spanned_pages; /* total size, including holes */

   unsigned long     present_pages; /* amount of memory (excluding holes) */

 

   /*

    * rarely used fields:

    */

   const char   *name;

} ____cacheline_internodealigned_in_smp;

 

Zone 里的per_cpu_pageset用于实现hot-cold 分配,把hot page放到CPUcache里处理148

Page frames(页帧)代表最小的内存单元,内核里用struct page结构体来表示内存里的页

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值