《Linux内核设计与实现》学习【7】—— 内存管理

本文深入解析Linux内存管理机制,涵盖页、区的概念及其结构,详细介绍了获取内存的方法,包括分配和释放连续物理页、按字节获取内存及虚拟地址连续页的分配。此外,还探讨了slab分配器的工作原理及其应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 概念

(1)页
  内核把物理页作为内存管理的基本单位,用struct page表示系统中的每个物理页。

struct page{
	unsigned long flags;		//页状态,是不是脏,是不是锁定在内存中
	atomic_t	_count;			// 引用计数
	atomic_t	_mapcount;		
	unsigned long private;		// 私有数据
	struct address_space *mapping;		//指向的页高速缓存
	pgoff_t index;	
	struct list_head lru;
	void *virtual;				// 页的虚拟地址,但高端内存并不永久地映射到内核地址空间,这个值为NULL
}

(2)区
  由于硬件的限制,内核并不能对所有页一视同仁。linux必须处理由如下2种由硬件存在缺陷而引起的内存寻址问题:

  • 一些硬件只能用某些特定的内存地址来执行DMA
  • 一些体系结构的内存的物理寻址方位比虚拟寻址范围大得多。使得一些内存不能永久地映射到内核空间上。
    linux主要使用四种区:
  • ZONE_DMA :包含的页能用来执行DMA操作
  • ZONE_DMA32:可用来执行DMA操作,只能被32位设备访问
  • ZONE_NORMAL:能正常映射的页
  • ZONE_HIGHEM: 包含高端内存,其中的页不能永久映射到内核地址空间

2 获取内存

2.1 获得页

//分配2^order(1<<order)个连续的物理页
struct page* alloc_pages(gfp_t gfp_mask, unsigned int order)

//释放页
void __free_pages(struct page *page, unsigned int order)
void free_pages(unsigned long addr, unsigned int order)
void free_page(unsigned long addr)

gfp_mask有3类:

  • 行为修饰符 :如何分配所需的内存
  • 区修饰符 :从哪个区分配内存
  • 类型修饰符:组合了行为修饰符和区修饰符,将各种可能的组合归纳为不同类型,简化使用

定义在 <linux/gfp.h>中

2.2 kmalloc

按字节获取内存

void * kmalloc(size_t size, gfp_t flags)

void kfree(const void *ptr)

2.3 vmalloc

void* vmalloc(unsigned long size)

void vfree(const void* addr)

kmalloc和vmalloc
kmalloc:分配的内存物理地址是连续的,虚拟地址也是连续的
vmalloc:分配的内存物理地址无须不连续的,虚拟地址是连续的
一般使用kmalloc。

3 slab

  slab分配器,用来存储内核中那些经常分配并释放的对象。
  slab层把不同的对象划分为高速缓存组,每个高速缓存组都存放不同类型的对象。
  这些高速缓存划分为slab,slab由一个或多个物理连续的页组成,一般是一个页。
  每个slab都包含一些对象成员。
在这里插入图片描述

slab描述符

struct slab{
	struct list_head list;		//满、部门满或空链表
	unsigned long colouroff;	//slab着色的偏移量
	void* s_mem;				//slab中的第一个对象
	unsigned int inuse;			//slab中已分配的对象数
	kmem_bufctl_t free;			//第一个空闲对象
}

接口

//创建高速缓存
struct kmem_cache *
kmem_cache_create (const char *name, size_t size, size_t align,
    unsigned long flags, void (*ctor)(void *))

//从高速缓存中分配对象
void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)

//向高速缓存释放对象
void kmem_cache_free(struct kmem_cache *cachep, void *objp)

//销毁高速缓存
void kmem_cache_destroy(struct kmem_cache *cachep)

4 分配函数选择

需要连续的物理页——选择低级页分配器或者 kmalloc 函数
需要虚拟地址上连续的页——vmalloc
需要高端内存——alloc_pages
创建和撤销很多大的数据结构——slab

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值