内核的内存使用不像用户空间那样随意,内核的内存出现错误时也只有靠自己来解决(用户空间的内存错误可以抛给内核来解决)。
所有内核的内存管理必须要简洁而且高效。
主要内容:
- 内存的管理单元
- 获取内存的方法
- 获取高端内存
- 内核内存的分配方式
- 总结
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 };