分享

linux内存管理分析【一】

 老匹夫 2014-09-12

尘 2012-11-19 21:07

#ifdef CONFIG_FLAT_NODE_MEM_MAP /* means !SPARSEMEM */

        struct page *node_mem_map;指向页结构的数组,该数组包含了节点中所有域的页

......

#ifndef CONFIG_NO_BOOTMEM

系统启动时会启用一套临时内存管理机制,struct bootmem_data就是该机制的管理结构

        struct bootmem_data *bdata;

#endif

......

node_start_pfn表示节点中第一个页帧编号。页帧的编号是全局统一的,在UMA系统中只有一个节点所以node_start_pfn为0.

        unsigned long node_start_pfn;

        unsigned long node_present_pages;结点中页帧的总数

        unsigned long node_spanned_pages; 结点中包括空洞在内的页帧总数

        int node_id;结点的编号

        wait_queue_head_t kswapd_wait;交换进程的等待队列

    struct task_struct *kswapd; 指向负责该结点的交换进程的task_struct 结构

    int kswapd_max_order; 由页交换子系统使用,定义要释放的区域大小。

    enum zone_type classzone_idx;

} pg_data_t;

1.2 内存域

系统中所有内存域类型由一个枚举结构来管理:

include/linux/mmzone.h

enum zone_type {

#ifdef CONFIG_ZONE_DMA

        ZONE_DMA, 适用于DMA的内存域

#endif

#ifdef CONFIG_ZONE_DMA32

使用32位寻址的适用于DMA的内存域,只有在64为系统中才与ZONE_DMA有差别

        ZONE_DMA32, 

#endif

        ZONE_NORMAL,可直接映射到内核段的普通内存域

#ifdef CONFIG_HIGHMEM

        ZONE_HIGHMEM,超出了内核段的物理内存

#endif

        ZONE_MOVABLE,伪内存域,防止物理内存碎片机制中要使用该内存域

        __MAX_NR_ZONES 可能有的内存域的总数

};

内存域管理结构struct zone在文件include/linux/mmzone.h中定义,如下:

struct zone {

数组watermark管理该内存域的三个水线值:

WMARK_HIGH:空闲页多余该值表示内存域的状态是理想的

WMARK_LOW:空闲页低于该值,内核开始将页换出到磁盘

WMARK_MIN:空闲页低于该值,急需空闲页,内存紧张

        unsigned long watermark[NR_WMARK];

当空闲页低于该值,采取一些方法计算空闲页的总数,避免内存漂移导致水线值失效

        unsigned long percpu_drift_mark;

保留一些空闲页,用于一些无论如何都不会失败的关键性分配

        unsigned long           lowmem_reserve[MAX_NR_ZONES];

        unsigned long           dirty_balance_reserve;

#ifdef CONFIG_NUMA

        int node;  所属的NUMA节点

当可回收的页超过此值时,将进行页面回收。

        unsigned long           min_unmapped_pages;当

内存管理区中,用于slab的可回收页大于此值时,将回收slab中的缓存页。

        unsigned long           min_slab_pages;

#endif

 每CPU的页面缓存, 当分配单个页面时,首先从该缓存中分配页面,可提高效率

        struct per_cpu_pageset __percpu *pageset;

该锁用于保护伙伴系统数据结构。即保护free_area相关数据。

        spinlock_t              lock;

当管理区中的所有页面都不可回收时设置此标志

        int                     all_unreclaimable; 

......

用于实现伙伴系统。这个数组定义了11个队列,每个队列中的元素都是大小为2^n的页面块。

        struct free_area        free_area[MAX_ORDER];

......

#ifdef CONFIG_COMPACTION

下面字段用于内存紧缩。

        unsigned int            compact_considered;

        unsigned int            compact_defer_shift;

        int                     compact_order_failed;

#endif

        ZONE_PADDING(_pad1_)确保后面的字段是缓存行对齐的

下面几个字段都跟页面回收相关

        spinlock_t              lru_lock;

        struct lruvec           lruvec;

        unsigned long           pages_scanned;     /* since last reclaim */

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

该内存区域中的各种统计信息,

        atomic_long_t           vm_stat[NR_VM_ZONE_STAT_ITEMS];

        unsigned int inactive_ratio;

        ZONE_PADDING(_pad2_)

等待队列,用于等待该区域内存的进程

        wait_queue_head_t       * wait_table;

        unsigned long           wait_table_hash_nr_entries;

        unsigned long           wait_table_bits;

        struct pglist_data      *zone_pgdat;指向该区域所属的结点

        unsigned long           zone_start_pfn;该区域的起始页帧号

        unsigned long           spanned_pages; 该区中包含空洞在内,总的页帧数

        unsigned long           present_pages; 总的页帧数,不包含空洞

        const char              *name;该区域的名字,如Normal、DMA、Highmem等

} ____cacheline_internodealigned_in_smp;

1.3 页面

系统中每个物理页面都有一个相关联的page结构用于记录该页面的状态

include/linux/mm_types.h

struct page {

页面标志,也包含了一些其他信息,比如页面所处的管理区编号等 

        unsigned long flags;  

如果最低位为0,则指向inode 的address_space,或则为NULL。如果页映射为匿名内存,最低位置位,而且该指针指向anon_vma对象

        struct address_space *mapping;  

......

                        struct {

                                union {

表示在也表中有多少项指向该页

                                        atomic_t _mapcount;

用于slub

                                        struct {

                                                unsigned inuse:16;

                                                unsigned objects:15;

                                                unsigned frozen:1;

                                        };

                                };

页的使用计数

                                atomic_t _count;

                        };

                };

        };

......

        union {

指向私有数据的指针,虚拟内存管理会忽略该数据。根据页的用途,可以用不同的方式使用该指针。

                unsigned long private; 

......

用于SLUB分配器,指向slab的指针

                struct kmem_cache *slab; 

用于复合页,指向首页   

                struct page *first_page;   

        };

用于高端内存区中的页,即无法直接映射到内核内存中的页。Virtual用于存储该页的虚拟地址。

        void *virtual;    

......

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多