linux内存分配与使用方法

分为用户空间和内核空间下的使用

一、用户空间:

需要包涵头文件:#include<malloc.h>
动态申请内存:malloc()
extern void *malloc(unsigned int num_bytes)
功能:分配长度为num_bytes字节的内存块
返回值:如果分配成功则返回指向被分配内存的指针,否则返回空指针

释放内存:free();

对申请到的内存操作的函数:头文件#include<string.h>
strcpy()
extern char *strcpy(char *dest,const char *src);
功能:把从src地址开始且含有NULL结束符的字符串赋值到以dest开始的地址空间
说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间容纳src的字符串
返回值:返回指向dest的指针。

memcpy()
void *memcpy(void *dest,const void *src,size_t n)
功能:由src指向地址为起始地址的连续n个字节的数据复制到以dest指向地址为起始地址的空间内。
返回:返回一个指向dest的指针

memcpy()与strcpy()相比,memcpy并不是遇到'\0'就结束,而是一定会拷贝完n个字节。

使用举例:
#include<stdio.h>
#include<string.h>
#include<malloc.h>

int main(int argc,char* argv[])
{
char *p;
char *a;
p = (char *) malloc(sizeof(char)*20);
a = "hello word -----";
//strcpy(p,a);
memcpy(p,a,16);
printf("%s\n",p);
printf("%s\n",strcpy(p,a));
free(p);
}

二、内核空间:需要包含头文件#include<linux/vmalloc.h> #include<string.h> #include<slab.h>

1、kmalloc() -- kfree()
申请函数:void *kmalloc(size_t size,int flags);
第一个参数是要分配的块的大小
第二个参数是分配标志。
此函数申请的内存位于物理内存映射区域,而且在物理上也是连续的
它们与真实的物理地址只有一个固定的偏移,存在较简单的转换关系。
释放函数:kfree()
============================================
使用例子:
#include<linux/vmalloc.h>
#include<string.h>
#include<slab.h>
...
unsigned char *kmallocmem;
...
static int xxx_init(void)
{
unsigned char *p;
p = "hello dong--";
kmallocmem = (unsigned char *)kmalloc(100,GFP_KERNEL);
memset(kmallocmem,0,100);
memcpy(kmallocmem,p,10);
printk("kmallocmem = %s\n",kmallocmem);
....
kfree(kmallocmem);
}
================================================

分配标志对应的值:
GFP_KERNEL = 208,最常用的标志,在内核空
间的进程中申请内存。
若暂时不能够满足,则进程会睡眠等待页,即会阻塞。
因此不能在中断上下文或持有自旋锁的时候使用此标志。
GFP_ATOMIC = 32 若不存在空闲页,则不等待,直接返回。
在中断处理函数、tasklet和内核定时器等非进程上下文中不能阻塞,
此时驱动中应该使用此标志来申请内存。
GFP_USER = 131280用来为用户空间分配内存,可能阻塞
GFP_HIGHUSER = 131282类似于GFP_USER,但是从高端内存分配
GFP_NOIO = 16不允许任何IO初始化
GFP_NOFS = 80不允许任何文件系统调用
__GFP_DMA = 1要求分配在能够DMA的内存区
__GFP_HIGHMEM = 2指示分配的内存可以位于高端内存
__GFP_COLD = 256请求一个较长时间不访问的页
__GFP_NOWARN = 512当一个分配无法满足时阻止内核发出警告
__GFP_HIGH = 32高优先级请求,允许获得被内核保留给紧急状况使用的最后的内存页
__GFP_REPEAT = 1024分配失败,则尽力重复尝试
__GFP_NOFAIL = 2048标志只许申请成功,不推荐
__GFP_NORETRY = 4096若申请不到,则立即放弃。

2、__get_free_pages() free_pages()
__get_free_page() free_page()

get_zeroed_page(unsigned int flags)该函数返回一个指向新页的指针并且将该页清零
__get_free_page(unsigned int flags)返回一个指向新页的指针但是该页不清零
__get_free_pages(unsigned int flags,unsigned int order)
该函数可分配多个页并返回分配内存的首地址
分配的页数为2^order,分配的页也不清零
order允许的最大值是10(即1024页)或11(2048页),依赖具体平台。
如果申请和释放的order不一样,则会引起内存混乱。。。。。
申请标志与kmalloc()完全一样。
============================================
使用例子:
#include<linux/vmalloc.h>
#include<string.h>
#include<slab.h>
...
unsigned char *pagemem;
...
static int xxx_init(void)
{
unsigned char *p;
p = "hello dong--";
pagemem = (unsigned char *)__get_free_page(0);
memset(pagemem,0,100);
memcpy(pagemem,p,10);
printk("pagemem = %s\n",pagemem);
....
free_page(pagemem);
}
==============================================

3、vmalloc() -- vfree()
void *vmalloc(unsigned long size);
一般用在为只存在软件中(没有对应的硬件意义)的较大的顺序缓冲区分配内存
vmalloc()远大于__get_free_pages()的开销,为了完成vmalloc()需要建立新的页表,
因此,调用vmalloc来分配少量内存是不妥的。
============================================
使用例子:
#include<linux/vmalloc.h>
#include<string.h>
#include<slab.h>
...
unsigned char *vmallocmem;
...
static int xxx_init(void)
{
unsigned char *p;
p = "hello dong--";
vmallocmem = (unsigned char *)vmalloc(1000000);
memset(vmallocmem,0,100);
memcpy(vmallocmem,p,10);
printk("vmallocmem = %s\n",vmallocmem);
....
vfree(vmallocmem);
}
==============================================

4、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 long));
用于创建一个slab缓存,它是一个可以驻留任意数目且全部同样大小的后备缓存。
size是要分配的每个数据结构的大小,
flags是控制如何进行分配的掩码:SLAB_NO_REAP即使内存紧缺也不自动收缩这块缓存
SLAB_HWCACHE_ALIGN每个数据对象被对齐到以个缓存
SLAB_CACHE_DMA要求数据对象在DMA内存区分配
...
分配slab缓存:
void *kmem_cache_alloc(struct kmem_cache *cachep,gfp_t flags)
上述函数在kmem_cache_create()创建的slab后备缓冲中分配一块并返回首地址指针

释放slab缓存:
void kmem_cache_free(struct kmem_cache *cachep,void *objp)
上述函数释放由kmem_cache_alloc()分配的缓存
收回slab缓存:
int kmem_cache_destroy(struct kmem_cache *cachep)
============================================
使用例子:
#include<linux/vmalloc.h>
#include<string.h>
#include<slab.h>
...
static struct kmem_cache_t *my_cachep;
...
static int xxx_init(void)
{
unsigned char *p;
struct my_cachep *ctx;
p = "hello dong--";
my_cachep = (unsigned char *)kmem_cache_create("my_cache",sizeof(my_cachep),
0,SLAB_HWCACHE_ALIGN,NULL);
ctx = (unsigned char *)kmem_cache_alloc(my_cachep,GFP_KERNEL);
memset(ctx,0,100);
memcpy(ctx,p,10);
printk("ctx = %s\n",ctx);
....
kmem_cache_free(my_cachep,ctx);
kmem_cache_destroy(my_cachep);
}
==============================================

5、内存池(类似于slab,也用于分配大量小对象的后备缓存)
创建内存池:
mempool_t *mempool_create(int min_nr,mempool_alloc_t *alloc_fn,
mempool_free_t *free_fn,void *pool_data);
用于创建一个内存池,min_nr参数是需要预分配对象的数目
alloc_fn和free_fn是指向内存池机制提供的标准对象和分配回收函数的指针
pool_data是分配和回收函数用到的指针
gfp_mask是分配标志,只有当__GFP_WAIT标记被指定时,分配函数才会休眠。
分配对象:
void *mempool_alloc(mempool_t *pool,int gfp_mask);
回收对象:
void mempool_free(void *element,mempool_t *pool);
回收缓存池:
void mempool_destroy(mempool_t *pool);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值