linux分配地址連續的大內存

kernel version 2.6.29
內核函數經常須要臨時分配一塊任意大小的物理地址連續的內存空間. 因此先介紹內核中兩個分配物理地址連續的內存空間的API.
node

kmalloc
因爲採用了SLUB 做爲默認內存分配器, 因此 kmalloc 工做於 SLUB 分配器之上。內核初始化時,建立一組共 13 個通用對象的緩衝區。kmalloc_caches 數組存放了這些緩衝區的 kmem_cache 數據結構(kmalloc_sizes.h)。因爲 kmem_cache 數據結構是經過 kmalloc 來分配的,故而只能用靜態分配的 kmem_cache 結構數組來描述通用對象的緩衝區。其中 kmalloc_caches[0] 表明的緩衝區專門分配 kmem_cache_node 結構。kmalloc_caches[1] 緩衝區對象大小爲64,kmalloc_caches[2] 緩衝區對象大小爲192,其他第 i(3-12)號緩衝區對象大小爲 2^i。若是請求分配超過物理頁面大小(4096)的對象,直接調用頁框分配器__get_free_pages.
算法

__get_free_pages
__get_free_pages 採用的內存分配方式爲Buddy算法. 因此通常分配的數據大小爲故是2 ^ order個頁面大小. 內核中定義了一個宏 MAX_ORDER, 表示一次請求能分配的最大物理頁數不能 >= MAX_ORDER, 也就是最大能夠分配到的內存塊. 2.6.29.6 中MAX_ORDER爲 11 即最大分配大小爲 ( 2 ^ 10 ) * 4096 = 4M.
數組


若是咱們須要在內核中分配4M以上的連續物理內存,怎麼辦,當前內核對應的方法還有兩個:
1> 使用static或全局變量數組, 直接定義變量大小爲所需數據大小.
例:
    static char buffer[ 512 * 1024 * 1024 ];
 定義512M大小數組. 不過此方法應用到模塊中話, 會致使加載模塊速度奇慢.
數據結構

2> 使用alloc_bootmem系列API在start_kernel調用mem_init()以前申請所需的連續大內存. 或添加一內核參數根據須要來調整數據緩衝大小. 不過此段內存也就永久保留, 除非直接引用所分配的內存地址.函數

例:
spa

    如下定義一內核參數pf_buf_len=nn[KMG],可定製分配的內存大小. 並EXPORT地址與長度信息.code

unsigned long long pf_buf_len = 0x0;
EXPORT_SYMBOL( pf_buf_len );

void *pf_buf_addr = NULL;
EXPORT_SYMBOL( pf_buf_addr );

static int __init pf_buf_len_setup(char *str)
{
    unsigned long long size;
    unsigned int       nid = 0;
    void              *pbuff = NULL;
 // 分析參數
    size = memparse( str, &str );
    if ( *str == '@' ){
        str ++;
        get_option( &str, &nid );
    }
    //printk( KERN_INFO "pf_buf_len: Allocating %llu bytes/n", size );
 // 分配內存
    pbuff = alloc_bootmem( size );
    if ( likely( NULL != pbuff ) ) {
        printk( KERN_INFO "pf_buf_len: Allocated %llu bytes at 0x%p(0x%p) on node %u/n",
            size, pbuff, (void *)virt_to_phys(pbuff), nid);
        pf_buf_addr = pbuff;
        pf_buf_len  = size;
        goto out;
    }
    printk( KERN_ERR "pf_buf_len: Allocated %llu bytes fail./n", size );
out:
    return 1;

}
__setup( "pf_buf_len=", pf_buf_len_setup);
相關文章
相關標籤/搜索