Linux设备驱动程序——分配内存

2520阅读 0评论2014-01-10 wangtisheng
分类:嵌入式

            Linux设备驱动程序
                            ——分配内存
        
仅为个人笔记,难免有错误~
一、Kmalloc函数的内幕
1.1 flags参数      
    kmalloc函数不对所获取的内存空间清零,分配给它的区域仍然保存原有的数据,这意味着要显式第清空内存,它分配的区域在屋里内存中也是连续的。其函数原型为:
    #include >
    void *kmalloc(size_t size, gfp_t flags);
    size    -- 要分配的块的大小
    flags   -- 分配标志,这些标志在中定义,常用的两个标志是GFP_KERNEL和GFP_ATOMIC
        GFP_KERNEL:Normal allocation of kernel memory. May sleep.
        GFP_ATOMIC:Used to allocate memory from interrupt handlers and other code outside of a process context. Never sleeps.
1.2 内存区段
    Linux内核把内存分为三个区段:可用于DMA的内存、常规内存以及高端内存
    可用于DMA的内存指存在于特定地址范围的内存,外设可以利用这些内存执行DMA访问。
    高端内存是32位平台为了访问大量的内存而存在的一种机制。

1.3 size参数
    内核负责管理系统屋里内存,物理内存只能按页面进行分配。内核只能分配一些预定义的、固定大小的字节数组。kmalloc能处理的最小的内存块是32或者64。kmalloc能够分配的内存块大小,存在一个上限,不应该分配大于128KB的内存(保障代码具有可移植性)。

二、后备高速缓存

    
设备驱动程序常常会反复地分配很多同一大小的内存块,内核实现了这种形式的内存池,称为高速缓存(lookaside cache)。   
    创建一个新的高速缓存对象:
    kmem_cache_t *kmem_cache_create(const char *name, size_t size,
                                    size_t offset,
                                    unsigned long flags,
                                    void (*constructor)(void *, kmem_cache_t *,
                                    unsigned long flags),
                                    void (*destructor)(void *, kmem_cache_t *,
                                    unsigned long flags));
    创建高速缓存对象之后,可以调用:
    void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags);
    释放内存对象时使用:
    void kmem_cache_free(kmem_cache_t *cache, const void *obj);
    释放高速缓存对象,该操作只有在已经从缓存中分配的所有对象都归还后才能成功。
    int kmem_cache_destroy(kmem_cache_t *cache);

三、内存池

四、get_free_page和相关函数    
    如果模块需要分配大块的内存,使用面向页的分配技术会更好。

    get_zeroed_page(unsigned int flags);
        Returns a pointer to a new page and fills the page with zeros.
    __get_free_page(unsigned int flags);
        Similar to get_zeroed_page, but doesn’t clear the page.
    __get_free_pages(unsigned int flags, unsigned int order);
        Allocates and returns a pointer to the first byte of a memory area that is potentially
several (physically contiguous) pages long but doesn’t zero the area.
    当程序不再使用页面是,需要释放它们。
    void free_page(unsigned long addr);    
    void free_pages(unsigned long addr, unsigned long order);
一个例子,来自国嵌

点击(此处)折叠或打开

  1. #include <linux/module.h>        //包含可装载模块需要的大量符合和函数的定义
  2. #include <linux/init.h>          //指定初始化和清除函数 

  3. char *buf1 = NULL;
  4. char *buf2 = NULL;

  5. int alloc_init()
  6. {
  7.     buf1 = kmalloc(100,GFP_KERNEL);
  8.     memset(buf1,0,100);
  9.     strcpy(buf1,"<<< --- Kmalloc Mem OK! --- >>>");
  10.     printk("<0>BUF 1 : %s\n",buf1);
  11.     
  12.     buf2 = get_zeroed_page(GFP_KERNEL);
  13.     strcpy(buf2,"<<<--- Get Free Page OK! --- >>>");
  14.     //printk("<0>BUF 2 : %s\n",buf2);
  15.     printk(KERN_EMERG "BUF 2: %s\n",buf2);
  16.     return 0;
  17. }

  18. void alloc_exit()
  19. {
  20.     kfree(buf1);
  21.     free_page(buf2);
  22.     printk("<0><<< --- Module Exit! --->>>\n");
  23. }

  24. module_init(alloc_init);
  25. module_exit(alloc_exit);

  26. MODULE_LICENSE("GPL")
实验现象:

上一篇:Linux设备驱动程序——高级字符驱动程序操作(按键的阻塞和非阻塞测试)
下一篇:Linux设备驱动程序——中断处理