LDD3源码分析之按页分配内存

来源:互联网 发布:云杉网络 垃圾 编辑:程序博客网 时间:2024/05/14 06:54

作者:刘昊昱 

博客:http://blog.csdn.net/liuhaoyutz

编译环境:Ubuntu 10.10

内核版本:2.6.32-38-generic-pae

LDD3源码路径:examples/scullp

 
一、scullp编译
本文分析LDD3第8章中按页分配内存相关代码,对应源码是examples/scullp目录下的相关文件。
这里首先说明一下,scullp的代码有两部分,一是main.c,另一部分是mmap.c,其中mmap.c主要实现了内存映射相关函数。因为本文主要分析按页分配内存,并且mmap.c涉及的内存映射在新的内核中有了很大变化。在本文中,我们不讨论mmap.c,并且为避免编译时出现的错误,编译时也不编译mmap.c。
要想在编译scullp模块时不编译mmap.c,只要做如下修改:
将Makefile第18行改为: scullp-objs := main.o
将main.c的第475行屏蔽掉: //.mmap =      scullp_mmap,
这样就不会编译mmap.c了。
即使不编译mmap.c,scullp在2.6.32-38-generic-pae内核下编译也会遇到很多问题,但是遇到的问题和解决方法和我在上一篇文章《LDD3源码分析之slab高速缓存》中讨论的是一样的,这里不详细说明了。
 
二、按页分配内存相关函数
如果模块需要分配大块的内存,最好按页分配,可使用如下函数:
get_zeroed_page(unsigned int flags);

分配一页内存,并将内存清零。
_ _get_free_page(unsigned int flags);

分配一页内存,但是不将内存清零。
_ _get_free_pages(unsigned int flags, unsigned int order);

分配若干页内存,其物理地址连续,返回指向第一个字节的指针,不清零页面。
参数flags和kmalloc函数中的一样。order是要申请页面数的以2为底的对数。
释放内存可使用如下函数:
void free_page(unsigned long addr);void free_pages(unsigned long addr, unsigned long order);

第一个函数是宏,展开后就是对第二个函数的调用。
 
三、scullp分析
scullp模块的代码和上一篇文章分析的scullc基本上一样,和scull也很类似。这里我们只分析最重要的代码。
scullp中分配内存的代码在scullp_write函数中:
243    /* Here's the allocation of a single quantum */244    if (!dptr->data[s_pos]) {245        dptr->data[s_pos] =246            (void *)__get_free_pages(GFP_KERNEL, dptr->order);247        if (!dptr->data[s_pos])248            goto nomem;249        memset(dptr->data[s_pos], 0, PAGE_SIZE << dptr->order);250    }

scullp释放内存的代码在scullp_trim函数中:
493    /* This code frees a whole quantum-set */494    for (i = 0; i < qset; i++)495        if (dptr->data[i])496           free_pages((unsigned long)(dptr->data[i]),497                      dptr->order);

代码很简单,从用户角度看,使用scullp速度更快了,使用内存效率更高了。测试scullp模块的过程如下图所示: