linux内存管理相关的函数有哪些

发布时间:2023-04-19 10:11:55 作者:iii
来源:亿速云 阅读:71

这篇文章主要介绍“linux内存管理相关的函数有哪些”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“linux内存管理相关的函数有哪些”文章能帮助大家解决问题。

linux内存管理相关的函数:1、kmalloc(),用于内核态的内存分配;2、vmalloc(),一般用在为只存在于软件中(没有对应的硬件意义)的较大的顺序缓冲区分配内存;3、alloc_page()和alloc_pages()函数,可以在内核空间分配;4、__get_free_pages()系列函数,返回一个或多个页面的虚拟地址;5、kmem_cache_alloc()等。

1、kmalloc()

kmalloc()函数类似与我们常见的malloc()函数,前者用于内核态的内存分配,后者用于用户态。
kmalloc()函数在物理内存中分配一块连续的存储空间,且和malloc()函数一样,不会清除里面的原始数据,如果内存充足,它的分配速度很快。其原型如下:

static inline void *kmalloc(size_t size, gfp_t flags);	/*返回的是虚拟地址*/

2、vmalloc()

vmalloc()一般用在为只存在于软件中(没有对应的硬件意义)的较大的顺序缓冲区分配内存,当内存没有足够大的连续物理空间可以分配时,可以用该函数来分配虚拟地址连续但物理地址不连续的内存。由于需要建立新的页表,所以它的开销要远远大于kmalloc及后面将要讲到的__get_free_pages()函数。且vmalloc()不能用在原子上下文中,因为它的内部实现使用了标志为 GFP_KERNEL 的kmalloc()。其函数原型如下:

void *vmalloc(unsigned long size);
void vfree(const void *addr);
static int xxx(...)
{
	...
	cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry) * cpuid->nent);
	if(!cpuid_entries)
	goto out;
	if(copy_from_user(cpuid_entries, entries, cpuid->nent * sizeof(struct kvm_cpuid_entry)))
		goto out_free;
	for(i=0; i<cpuid->nent; i++){
		vcpuid->arch.cpuid_entries[i].eax = cpuid_entries[i].eax;
		...
		vcpuid->arch.cpuid_entries[i].index = 0;
	}
	...
out_free:
	vfree(cpuid_entries);
out:
	return r;
}

3、页分配函数

在linux中,内存分配是以页为单位的,32位机中一页为4KB,64位机中,一页为8KB,但具体还有根据平台而定。
根据返回值类型的不同,页分配函数分为两类,一是返回物理页地址,二是返回虚拟地址。虚拟地址和物理地址起始相差一个固定的偏移量。

#define __pa(x) ((x) - PAGE_OFFSET)
static inline unsigned long virt_to_phys(volatile void *address)
{
	return __pa((void *)address);
}

#define __va(x) ((x) + PAGE_OFFSET)
static inline  void* phys_to_virt(unsigned long address)
{
	return __va(address);
}

linux内存管理相关的函数有哪些

根据返回页面数目分类,分为仅返回单页面的函数和返回多页面的函数。

3.1 alloc_page()和alloc_pages()函数

该函数定义在头文件/include/linux/gfp.h中,它既可以在内核空间分配,也可以在用户空间分配,它返回分配的第一个页的描述符而非首地址,其原型为:

#define alloc_page(gfp_mask)  alloc_pages(gfp_mask, 0)
#define alloc_pages(gfp_mask, order) alloc_pages_node(numa_node_id(), gfp_mask, order)  //分配连续2^order个页面
static inline struct page *alloc_pages_node(int nid, gfp_t gfp_mask, unsigned int order) 
{
	if(unlikely(order >= MAX_ORDER))
		return NULL;
	if(nid < 0)
		nid = numa_node_id();
	return __alloc_pages(gfp_mask, order, noed_zonelist(nid, gfp_mask));
}

3.2 __get_free_pages()系列函数

它是kmalloc函数实现的基础,返回一个或多个页面的虚拟地址。该系列函数/宏包括 get_zeroed_page()_ _get_free_page()_ _get_free_pages()。在使用时,其申请标志的值及含义与 kmalloc()完全一样,最常用的是 GFP_KERNEL 和 GFP_ATOMIC。

/*分配多个页并返回分配内存的首地址,分配的页数为2^order,分配的页不清零。
order 允许的最大值是 10(即 1024 页)或者 11(即 2048 页),依赖于具体
的硬件平台。*/
unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)
{
	struct page *page;
	page = alloc_pages(gfp_mask, order);
	if(!page)
		return 0;
	return (unsigned long)page_address(page);
}

#define __get_free_page(gfp_mask)  __get_free_pages(gfp_mask, 0)

/*该函数返回一个指向新页的指针并且将该页清零*/
unsigned long get_zeroed_page(unsigned int flags);
#define __free_page(page) __free_pages((page), 0)
#define free_page(addr) free_pages((addr), 0)

void free_pages(unsigned long addr, unsigned int order)
{
	if(addr != 0){
		VM_BUG_ON(!virt_addr_valid((void*)addr));
		__free_pages(virt_to_page((void *)addr), order);
	}
}

void __free_pages(struct page *page, unsigned int order)
{
	if(put_page_testzero(page)){
		if(order == 0)
			free_hot_page(page);
		else
			__free_pages_ok(page, order);
	}
}

free_pages()函数是调用__free_pages()函数完成内存释放的。

4、slab缓存

4.1 创建slab缓存区

该函数创建一个slab缓存(后备高速缓冲区),它是一个可以驻留任意数目全部同样大小的后备缓存。其原型如下:

struct kmem_cache *kmem_cache_create(const char *name, size_t size, \
									 size_t align, unsigned long flags,\
									 void (*ctor)(void *, struct kmem_cache *, unsigned long),\
									 void (*dtor)(void *, struct kmem_cache *, unsigned ong)));

其中:
name:创建的缓存名;
size:可容纳的缓存块个数;
align:后备高速缓冲区中第一个内存块的偏移量(一般置为0);
flags:控制如何进行分配的位掩码,包括 SLAB_NO_REAP(即使内存紧缺也不自动收缩这块缓存)、SLAB_HWCACHE_ALIGN ( 每 个 数 据 对 象 被 对 齐 到 一 个 缓 存 行 )、SLAB_CACHE_DMA(要求数据对象在 DMA 内存区分配)等);
ctor:是可选的内存块对象构造函数(初始化函数);
dtor:是可选的内存对象块析构函数(释放函数)。

4.2 分配slab缓存函数

一旦创建完后备高速缓冲区后,就可以调用kmem_cache_alloc()在缓存区分配一个内存块对象了,其原型如下:

void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags);

cachep指向开始分配的后备高速缓存,flags与传给kmalloc函数的参数相同,一般为GFP_KERNEL。

4.3 释放slab缓存

该函数释放一个内存块对象:

void *kmem_cache_free(struct kmem_cache *cachep, void *objp);

4.4 销毁slab缓存

kmem_cache_create对应的是销毁函数,释放一个后备高速缓存:

int kmem_cache_destroy(struct kmem_cache *cachep);

它必须等待所有已经分配的内存块对象被释放后才能释放后备高速缓存区。

4.5 slab缓存使用举例

创建一个存放线程结构体(struct thread_info)的后备高速缓存,因为在linux中涉及频繁的线程创建与释放,如果使用__get_free_page()函数会造成内存的大量浪费,效率也不高。所以在linux内核的初始化阶段就创建了一个名为thread_info的后备高速缓存,代码如下:

/* 创建slab缓存 */
static struct kmem_cache *thread_info_cache;
thread_info_cache = kmem_cache_create("thread_info", sizeof(struct thread_info), \
										SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);

/* 分配slab缓存 */
struct thread_info *ti;
ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL);

/* 使用slab缓存 */
...
/* 释放slab缓存 */
kmem_cache_free(thread_info_cache, ti);
kmem_cache_destroy(thread_info_cache);

5、内存池

在 Linux 内核中还包含对内存池的支持,内存池技术也是一种非常经典的用于分配大量小对象的后备缓存技术。

5.1 创建内存池

mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn, \
 							mempool_free_t *free_fn, void *pool_data);

mempool_create()函数用于创建一个内存池,min_nr 参数是需要预分配对象的数目,alloc_fn 和 free_fn 是指向内存池机制提供的标准对象分配和回收函数的指针,其原型分别为:

typedef void *(mempool_alloc_t)(int gfp_mask, void *pool_data); 

typedef void (mempool_free_t)(void *element, void *pool_data);

pool_data 是分配和回收函数用到的指针,gfp_mask 是分配标记。只有当_ _GFP_WAIT 标记被指定时,分配函数才会休眠。

5.2 分配和回收对象

在内存池中分配和回收对象需由以下函数来完成:

void *mempool_alloc(mempool_t *pool, int gfp_mask); 
void mempool_free(void *element, mempool_t *pool);

mempool_alloc()用来分配对象,如果内存池分配器无法提供内存,那么就可以用预分配的池。

5.3 销毁内存池

void mempool_destroy(mempool_t *pool);

mempool_create()函数创建的内存池需由 mempool_destroy()来回收。

关于“linux内存管理相关的函数有哪些”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注亿速云行业资讯频道,小编每天都会为大家更新不同的知识点。

推荐阅读:
  1. Linux I2C App开发的示例分析
  2. Linux可重入、异步信号安全和线程安全的知识点有哪些

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

linux

上一篇:linux句柄数指的是什么

下一篇:linux是否自带有ssh

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》