Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1259000
  • 博文数量: 85
  • 博客积分: 10051
  • 博客等级: 上将
  • 技术积分: 2835
  • 用 户 组: 普通用户
  • 注册时间: 2005-12-21 14:33
文章分类

全部博文(85)

文章存档

2011年(15)

2010年(37)

2009年(17)

2008年(16)

我的朋友

分类: LINUX

2008-03-07 00:37:59

在内核中可以以页面为单位进行内存的分配,相关的接口定义在include/linux/gfp.h中。

最核心的分配页面函数为:
    struct page * alloc_pages(unsigned int gfp_mask, unsigned int order)
    在NUMA开启的情况下,是一个static inline的函数,而在其他情况下,是一个宏。这个函数分配2order次方个连续的物理页面,返回指向第一个页的page结构体。

   如果只想分配一个页面,则可以使用alloc_page(),其实是这样一个宏:
    #define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)
   
得到struct page后,怎么知道页的逻辑地址呢:

    void * page_address(struct page * page)
     返回一个指向给定物理页当前所在的逻辑地址。

    当只需要逻辑地址,而无须struct page时,可以使用下列函数进行分配:
    unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int order)
  
申请连续的2order次方个连续页面,返回第一个页的逻辑地址
  
    unsigned long __get_free_page(unsigned int gfp_mask)
   
申请一个页面并返回其逻辑地址。

而想释放一个页面的时候,与分配对应如下:

    void _free_pages(struct page * page, unsigned int order)
   
释放page结构体指向的连续2order次方个页面。

    void free_pages(unsigned long addr, unsigned int order)
   
释放从地址addr开始的,连续2order次方个页面。

    void free_page(unsigned long addr)
   
释放地址addr的一个页。

如果想得到初始化为0的页面,可以使用:

    unsigned long get_zeroed_page(unsigned int gfp_mask)

  第一次用这样的函数,比较晕下面记下一个关于如何映射到结构体数组来操作样例吧(主要是为了配合原有的带struct list_head的数据结构来使用)


struct abc
{
       struct list_head my_list;
       int a;
}

// Allocate a zeroed page.

struct abc * aaa = (struct abc *) get_zeroed_page(GFP_KERNEL);

//Free that page.

free_page((unsigned long)(aaa));



后记:这次算是第一次修改内核,读代码和改代码的差异随着一次次的panic不慌不忙地展现出来,我似乎是第一次认识到了处在kernel空间的危险性...
阅读(965) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~