内核的内存使用不像用户空间那样随意,内核的内存出现错误时也只有靠自己来解决(用户空间的内存错误可以抛给内核来解决)。

所有内核的内存管理必须要简洁而且高效。

主要内容:

  • 内存的管理单元
  • 获取内存的方法
  • 获取高端内存
  • 内核内存的分配方式
  • 总结

 

1. 内存的管理单元

内存最基本的管理单元是页,同时按照内存地址的大小,大致分为3个区。

 

1.1 页

页的大小与体系结构有关,在 x86 结构中一般是 4KB或者8KB。

可以通过 getconf 命令来查看系统的page的大小:

[wangyubin@localhost ]$ getconf -a | grep -i 'page'

PAGESIZE                           4096
PAGE_SIZE                          4096
_AVPHYS_PAGES                      637406
_PHYS_PAGES                        2012863

 

以上的 PAGESIZE 就是当前机器页大小,即 4KB

 

页的结构体头文件是: <linux/mm_types.h> 位置:include/linux/mm_types.h

/*
 * 页中包含的成员非常多,还包含了一些联合体
 * 其中有些字段我暂时还不清楚含义,以后再补上。。。
 */
struct page {
    unsigned long flags;    /* 存放页的状态,各种状态参见<linux/page-flags.h> */
    atomic_t _count;        /* 页的引用计数 */
    union {
        atomic_t _mapcount;    /* 已经映射到mms的pte的个数 */
        struct {        /* 用于slab层 */
            u16 inuse;
            u16 objects;
        };
    };
    union {
        struct {
        unsigned long private;        /* 此page作为私有数据时,指向私有数据 */
        struct address_space *mapping;    /* 此page作为页缓存时,指向关联的address_space */
        };
#if USE_SPLIT_PTLOCKS
        spinlock_t ptl;
#endif
        struct kmem_cache *slab;    /* 指向slab层 */
        struct page *first_page;    /* 尾部复合页中的第一个页 */
    };
    union {
        pgoff_t index;        /* Our offset within mapping. */
        void *freelist;        /* SLUB: freelist req. slab lock */
    };
    struct list_head lru;    /* 将页关联起来的链表项 */
#if defined(WANT_PAGE_VIRTUAL)
    void *virtual;            /* 页的虚拟地址 */
#endif /* WANT_PAGE_VIRTUAL */
#ifdef CONFIG_WANT_PAGE_DEBUG_FLAGS
    unsigned long debug_flags;    /* Use atomic bitops on this */
#endif

#ifdef CONFIG_KMEMCHECK
    /*
     * kmemcheck wants to track the status of each byte in a page; this
     * is a pointer to such a status block. NULL if not tracked.
     */
    void *shadow;
#endif
};
View Code

 

相关文章: