linux内存管理之malloc、kmalloc、kzalloc、vmalloc的区别

linux内存管理之malloc、kmalloc、kzalloc、vmalloc的区别

1 用户空间申请内存的方式

1.1 函数原型

void *malloc(unsigned int num_bytes);

1.2 函数解释和说明

如果分配成功则返回指向被分配内存的指针(此存储区中的初始值不确定),否则返回空指针NULL。

1.3 释放函数

对应的释放函数是free();

2 内核空间申请内存的方式

2.1 kmalloc

2.1.1 函数原型

void *kmalloc(size_t size, gfp_t flags);

2.1.2 flags参数说明

1)GFP_KERNEL
内核内存分配时最常用的,无内存可用时可引起休眠,在中断上下文或持有自旋锁的时候不能使用 GFP_KERNE 申请内存 。
2)GFP_ATOMIC
用来从中断处理和进程上下文之外的其他代码中分配内存,从不睡眠,在中断处理函数、tasklet 和内核定时器等非进程上下文中不能阻塞,此时驱动应当使用 GFP_ATOMIC 标志来申请内存。当使用 GFP_ATOMIC 标志申请内存时,若不存在空闲页,则不等待,直接返回。
3)GFP_DMA
给 DMA 控制器分配内存,需要使用该标志(DMA要求分配虚拟地址和物理地址连续)

2.1.3 size参数说明

1)最小申请的内存大小为32字节或64字节(受系统影响)
2)最大申请的内存大小一般不超过128K(受系统影响)
3)kmalloc申请的内存在物理地址上是连续的,物理地址和虚拟地址之间存在一个固定偏移量;即虚拟内存的大小和物理内存的大小一样。

2.1.4 kmalloc函数作用

1)kmalloc是基于slab分配机制实现的
2)返回速度快(除非被阻塞)
3)分配的内存不进行任何初始化(清零)操作,分配的内存区域仍然保留有他原有的内容;

2.1.5 释放函数

void kfree(const void *objp);

2.1.6 linux源码解析

static __always_inline void *kmalloc(size_t size, gfp_t flags)
{
	if (__builtin_constant_p(size)) {  //用于编译器的优化,size是不是常量
		if (size > KMALLOC_MAX_CACHE_SIZE) //用于确认最大开辟空间,该值为8K
                        //用于申请大内存,以page为粒度的申请,该函数最终调用的是alloc_pages函数,用的是伙伴系统
			return kmalloc_large(size, flags);
#ifndef CONFIG_SLOB
		if (!(flags & GFP_DMA)) {
			int index = kmalloc_index(size);
 
			if (!index)
				return ZERO_SIZE_PTR;
                        //用于申请小内存,最后使用slab_slloc来完成
			return kmem_cache_alloc_trace(kmalloc_caches[index],
					flags, size);
		}
#endif
	}
	return __kmalloc(size, flags);
}

2.2 kzalloc

2.2.1 函数原型

void *kzalloc(size_t size, gfp_t flags);

2.2.2 kzalloc函数说明

1)kzalloc()函数与 kmalloc()非常相似,参数及返回值一样
2)kzalloc()基于kmalloc实际上只是额外附加了 __GFP_ZERO 标志。所以它除了申请内核内存外,还会对申请到的内存内容清零

2.2.3 释放函数

释放函数仍然为void kfree(const void *objp);

2.3 valloc

2.3.1 函数原型

void *vmalloc(unsigned long size);

2.3.2 vmalloc函数说明

1)会在虚拟内存空间给出一块连续的内存区,但这片连续的虚拟内存在物理内存中并不一定连续。
2)申请的内存大小没有限制,如果需要申请较大的内存空间就需要用此函数
3)vmalloc() 和 vfree() 可以睡眠,因此不能从中断上下文调用。

2.3.2 释放函数

void vfree(const void *addr);

3 申请内存总结

3.1 相同点

1)用于申请内核空间的内存;
2)内存以字节为单位进行分配;
3)所分配的内存虚拟地址上连续;
4)都是基于slab机制

3.2 区别

1)kzalloc 是强制清零的 kmalloc 操作;(以下描述不区分 kmalloc 和 kzalloc)
2)kmalloc 分配的内存大小有限制(128K),而 vmalloc 没有限制;
3) kmalloc 可以保证分配的内存物理地址是连续的,但是 vmalloc 不能保证;
4) kmalloc 分配内存的过程可以是原子过程(使用 GFP_ATOMIC),而 vmalloc 分配内存时则可能产生阻塞;
5)kmalloc 分配内存的开销小,因此 kmalloc 比 vmalloc 要快;
6)kmalloc 可以用于直接DMA传输

你可能感兴趣的:(Linux,linux)