网站公告列表

  没有公告

加入收藏
设为首页
联系本站
您现在的位置: AnalogCN安诺电子 >> 文章 >> 技术交流 >> 文章正文
  uclinux2.6(bf561)中的bootmem分析(4):alloc_bootmem_pages           ★★★ 【字体:
uclinux2.6(bf561)中的bootmem分析(4):alloc_bootmem_pages
作者:快乐虾    文章来源:http://blog.csdn.net/lights_joy    点击数:    更新时间:2008-5-13    
这是一个定义好的宏,用于分配内存:
#define alloc_bootmem_pages(x) \
     __alloc_bootmem(x, PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
其中MAX_DMA_ADDRESS的定义为:
#define MAX_DMA_ADDRESS PAGE_OFFSET
而PAGE_OFFSET是定义成0的。
__pa的定义为:
#define __pa(vaddr)         virt_to_phys((void *)(vaddr))
virt_to_phys的定义为:
#define virt_to_phys(vaddr) ((unsigned long) (vaddr))
实际上,alloc_bootmem_pages这个宏就变成了
#define alloc_bootmem_pages(x) \
     __alloc_bootmem(x, PAGE_SIZE, 0)
看看__alloc_bootmem的实现代码:
 
void * __init __alloc_bootmem(unsigned long size, unsigned long align,
                    unsigned long goal)
{
     void *mem = __alloc_bootmem_nopanic(size,align,goal);
 
     if (mem)
         return mem;
     /*
      * Whoops, we cannot satisfy the allocation request.
      */
     printk(KERN_ALERT "bootmem alloc of %lu bytes failed!\n", size);
     panic("Out of memory");
     return NULL;
}
再看看的__alloc_bootmem_nopanic实现:
 
void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align,
                         unsigned long goal)
{
     bootmem_data_t *bdata;
     void *ptr;
 
     list_for_each_entry(bdata, &bdata_list, list) {
         ptr = __alloc_bootmem_core(bdata, size, align, goal, 0);
         if (ptr)
              return ptr;
     }
     return NULL;
}
前面说过bdata_list实际上只有一个元素,因此这一循环将只执行一次,__alloc_bootmem_core的实现在bootmem.c中,代码较长。先看看注释和声明:
 
/*
 * We 'merge' subsequent allocations to save space. We might 'lose'
 * some fraction of a page if allocations cannot be satisfied due to
 * size constraints on boxes where there is physical RAM space
 * fragmentation - in these cases (mostly large memory boxes) this
 * is not a problem.
 *
 * On low memory boxes we get it right in 100% of the cases.
 *
 * alignment has to be a power of 2 value.
 *
 * NOTE: This function is _not_ reentrant.
 */
void * __init
__alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
           unsigned long align, unsigned long goal, unsigned long limit)
{
当调用到这里的时候goal和limit的值都为0,align为页面大小4K。
以下代码显示了__alloc_bootmem的页面分配策略:
restart_scan:
     for (i = preferred; i < eidx; i += incr) {
         unsigned long j;
         i = find_next_zero_bit(bdata->node_bootmem_map, eidx, i);
         i = ALIGN(i, incr);
         if (i >= eidx)
              break;
         if (test_bit(i, bdata->node_bootmem_map))
              continue;
         for (j = i + 1; j < i + areasize; ++j) {
              if (j >= eidx)
                   goto fail_block;
              if (test_bit(j, bdata->node_bootmem_map))
                   goto fail_block;
         }
         start = i;
         goto found;
     fail_block:
         i = ALIGN(j, incr);
     }
在上面的代码中,prefeered为0,areasize表示总共要求分配的页数,incr取1。很简单,就是沿着页表从低往高找,找到第一个可用的页块。
当分配成功后,此函数将记录这次分配的信息:
found:
     bdata->last_success = PFN_PHYS(start);
     BUG_ON(start >= eidx);
 
     /*
      * Is the next page of the previous allocation-end the start
      * of this allocation's buffer? If yes then we can 'merge'
      * the previous partial page with this allocation.
      */
     if (align < PAGE_SIZE &&
         bdata->last_offset && bdata->last_pos+1 == start) {
        
     } else {
         bdata->last_pos = start + areasize - 1;
         bdata->last_offset = size & ~PAGE_MASK;
         ret = phys_to_virt(start * PAGE_SIZE + bdata->node_boot_start);
     }
 
     /*
      * Reserve the area now:
      */
     for (i = start; i < start + areasize; i++)
         if (unlikely(test_and_set_bit(i, bdata->node_bootmem_map)))
              BUG();
     memset(ret, 0, size);
     return ret;
还有一个值得注意的是在分配成功之后,此函数还负责将这段内存清0。
文章录入:admin    责任编辑:admin 
  • 上一篇文章:

  • 下一篇文章:
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    最新热点 最新推荐 相关文章
    前置放大器在移动医疗服务系
    便携式多通道大容量生理信号
    防腐监测仪的设计与应用
    基于AD1674的酶标仪的设计
    基于C/S模式的JRTPLIB库的测
    ffmpeg与jrtplib相结合应用
    blackfin模拟摄像头驱动中的
    可编程逻辑在数字信号处理系
    发现VDSP4.5一个BUG:单步调
    VDSP5.0双核工程下sml3中的变
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    版权所有:AnalogCN安诺电子 湘ICP备06016315号