LINUX核心記憶體管理kmalloc,vmalloc

來源:互聯網
上載者:User

標籤:

一.kmalloc與vmallco

    在裝置驅動程式或者核心模組中動態開闢記憶體,不是用malloc,而是kmalloc ,vmalloc,釋放記憶體用的是kfree,vfree,kmalloc函數返回的是虛擬位址(線性地址). kmalloc特殊之處在於它分配的記憶體是物理上連續的,這對於要進行DMA的裝置十分重要. 而用vmalloc分配的記憶體只是線性地址連續,物理地址不一定連續,不能直接用於DMA。vmalloc函數的工作方式類似於kmalloc,只不過前者分配的記憶體虛擬位址是連續的,而物理地址則無需連 續。通過vmalloc獲得的頁必須一個一個地進行映射,效率不高, 因此,只在不得已(一般是為了獲得大塊記憶體)時使用。vmalloc函數返回一個指標,指向邏輯上連續的一塊記憶體區,其大小至少為size。在發生錯誤 時,函數返回NULL。vmalloc可能睡眠,因此,不能從中斷上下文中進行調用,也不能從其它不允許阻塞的情況下調用。要釋放通過vmalloc所獲 得的記憶體,應使用vfree函數

    vmalloc和kmalloc的分配記憶體的特點大概如下:

        

  區別大概可總結為:

      1,vmalloc分配的一般為高端記憶體,只有當記憶體不夠的時候才分配低端記憶體;kmallco從低端記憶體配置。

      2,vmalloc分配的物理地址一般不連續,而kmalloc分配的地址連續,兩者分配的虛擬位址都是連續的;

      3,vmalloc分配的一般為大塊記憶體,而kmaooc一般分配的為小塊記憶體,(一般不超過128k);

   

二.DMA工作

    為了減少CPU對快速裝置入出的操作,可以通過把這 批資料的傳輸過程交由一塊專用的介面卡(DMA介面)來控制,讓DMA卡代替CPU控制在快速裝置與主儲存空間之間直接傳輸資料,其大概工作的機制是在DMA模式下,CPU只須向DMA控制器下達指令,讓DMA控制器來處理資料的傳送,資料傳送完畢再把資訊反饋給CPU,這樣就很大程度上減輕了 CPU資源佔有率。

    工作大概如下:

            

 

    以下是測試的代碼:

          

  1 #include <linux/init.h>  2 #include <linux/thread_info.h>  3 #include <linux/module.h>  4 #include <linux/sched.h>  5 #include <linux/errno.h>  6 #include <linux/kernel.h>  7 #include <linux/module.h>  8 #include <linux/slab.h>  9 #include <linux/input.h> 10 #include <linux/init.h> 11 #include <linux/serio.h> 12 #include <linux/delay.h> 13 #include <linux/clk.h> 14 #include <linux/miscdevice.h> 15 #include <linux/io.h> 16 #include <linux/ioport.h> 17 #include <linux/vmalloc.h> 18 #include <linux/dma-mapping.h> 19 #include <linux/export.h> 20 #include <linux/gfp.h> 21  22 #include <asm/dma-mapping.h> 23 #include <asm/uaccess.h> 24  25 #include <linux/gpio.h> 26 #include <mach/gpio.h> 27 #include <plat/gpio-cfg.h> 28  29 MODULE_LICENSE("GPL"); 30 MODULE_AUTHOR("bunfly"); 31  32  33 unsigned long vmalloc_to_pfn(const void *vmalloc_addr); 34 int test_init() 35 { 36     int ret = 0; 37     unsigned char *vmalloc_virt, *normal_virt, *phys; 38     unsigned long pfn; 39  40     printk("KERNEL SPACE: init\n"); 41  42     printk("KERNEL SPACE: read from d0003000: %s\n", 0xd0003000); 43     //讀出d0003000虛擬位址裡面的資料 44  45     normal_virt = kmalloc(40, GFP_KERNEL); 46     //kmalloc分配一段虛擬位址,大小,睡眠不可中斷 47  48     phys = virt_to_phys(normal_virt); 49     printk("KMAKLLOC: kmalloc virt: %p <==> phys: %p\n", normal_virt, phys); 50  51     kfree(normal_virt); 52  53     //分配頁 54     //-------------------------------------- 55     vmalloc_virt = vmalloc(500); 56     //vmalloc分配記憶體 57  58     pfn = vmalloc_to_pfn(vmalloc_virt); 59     //頁分配 60     phys = (pfn << 12) | ((unsigned long)vmalloc_virt & 0xfff); 61     //將頁地址轉換成物理地址 62     normal_virt = phys_to_virt(phys); 63     //再將物理地址轉換成虛擬位址 64     printk("VMALLOC: vmalloc_virt = %p, normal_virt = %p\n", vmalloc_virt, normal_virt); 65  66     //dma分配 67     normal_virt = dma_alloc_coherent(NULL, 1024, &phys, GFP_KERNEL); 68     printk("DMA: vmalloc_virt = %p, normal_virt = %p\n", vmalloc_virt,phys); 69     dma_free_coherent(NULL, 1024, normal_virt, phys); 70  71     vfree(vmalloc_virt); 72     return 0; 73 } 74  75 void test_exit() 76 { 77     printk("KERNEL SPACE: exit\n"); 78 } 79  80 module_init(test_init); 81 module_exit(test_exit); 82 ~                                                                                                                                                                                                                                                                                                                                                                                                                                  ~                                                                                                                                                                                                                                                                                                                                                                                                                                  ~  

      首先,在50003000地址放入資料,然後在d0003000的物理地址中讀出資料:

      

      查看50003000地址中的資料:

      

 

      啟動控制板子,插入模組,運行結果:

       

      可以看到kmalloc的物理地址是低端記憶體的,(從40000000開始),而vmalloc分配的物理地址是高端記憶體,而通過    DMA記憶體的也是低端一點的。

  補充說明:kmalloc函數原型:

   static __always_inline void *kmalloc(size_t size, gfp_t flags)
        其中falgs有

      

      主要的要分配兩種:一般都是

            GFP_KERNLE;核心使用記憶體--------可以睡眠

            GFP_USER;   使用者空間記憶體;

            GFP_ATOMIC;  原子分配  ---------不可以睡眠

    核心編程的法則:

        中斷上下文不可以睡眠(可以用is_inetrruput()函數查看是否是中斷處理調用函數,返回1為真)

LINUX核心記憶體管理kmalloc,vmalloc

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.