zoukankan      html  css  js  c++  java
  • kmalloc、kzalloc和vmalloc

    kmalloc

    函数原型:

    void *kmalloc(size_t size, gfp_t flags);

      kmalloc() 申请的内存位于物理内存映射区域,而且在物理上也是连续的,它们与真实的物理地址只有一个固定的偏移,因为存在较简单的转换关系,所以对申请的内存大小有限制,不能超过128KB。 
       
    较常用的 flags(分配内存的方法):

    • GFP_ATOMIC —— 分配内存的过程是一个原子过程,分配内存的过程不会被(高优先级进程或中断)打断;
    • GFP_KERNEL —— 正常分配内存;
    • GFP_DMA —— 给 DMA 控制器分配内存,需要使用该标志(DMA要求分配虚拟地址和物理地址连续)。

    flags 的参考用法: 
     |– 进程上下文,可以睡眠     GFP_KERNEL 
     |– 进程上下文,不可以睡眠    GFP_ATOMIC 
     |  |– 中断处理程序       GFP_ATOMIC 
     |  |– 软中断          GFP_ATOMIC 
     |  |– Tasklet         GFP_ATOMIC 
     |– 用于DMA的内存,可以睡眠   GFP_DMA | GFP_KERNEL 
     |– 用于DMA的内存,不可以睡眠  GFP_DMA |GFP_ATOMIC 
       
    对应的内存释放函数为:

    void kfree(const void *objp);

    kzalloc
    /** * kzalloc - allocate memory. The memory is set to zero. * @size: how many bytes of memory are required. * @flags: the type of memory to allocate (see kmalloc). */
    static inline void *kzalloc(size_t size, gfp_t flags){ return kmalloc(size, flags | __GFP_ZERO);}  kzalloc() 函数与 kmalloc() 非常相似,参数及返回值是一样的,可以说是前者是后者的一个变种,因为 kzalloc() 实际上只是额外附加了 __GFP_ZERO 标志。所以它除了申请内核内存外,还会对申请到的内存内容清零。

    kzalloc() 对应的内存释放函数也是 kfree()。

    vmalloc
    void *
    vmalloc(unsigned long size);函数原型:

      vmalloc() 函数则会在虚拟内存空间给出一块连续的内存区,但这片连续的虚拟内存在物理内存中并不一定连续。由于 vmalloc() 没有保证申请到的是连续的物理内存,因此对申请的内存大小没有限制,如果需要申请较大的内存空间就需要用此函数了。

    对应的内存释放函数为:

    void vfree(const void *addr);

    注意:vmalloc() 和 vfree() 可以睡眠,因此不能从中断上下文调用。 
      

    用于申请内核空间的内存;kmalloc()、kzalloc()、vmalloc() 的共同特点是:

    1. 内存以字节为单位进行分配;
    2. 所分配的内存虚拟地址上连续;

    kmalloc()、kzalloc()、vmalloc() 的区别是:

    1. kzalloc 是强制清零的 kmalloc 操作;(以下描述不区分 kmalloc 和 kzalloc)
    2. kmalloc 分配的内存大小有限制(128KB),而 vmalloc 没有限制;
    3. kmalloc 可以保证分配的内存物理地址是连续的,但是 vmalloc 不能保证;
    4. kmalloc 分配内存的过程可以是原子过程(使用 GFP_ATOMIC),而 vmalloc 分配内存时则可能产生阻塞;
    5. kmalloc 分配内存的开销小,因此 kmalloc 比 vmalloc 要快;

    一般情况下,内存只有在要被 DMA 访问的时候才需要物理上连续,但为了性能上的考虑,内核中一般使用 kmalloc(),而只有在需要获得大块内存时才使用 vmalloc()。例如,当模块被动态加载到内核当中时,就把模块装载到由 vmalloc() 分配的内存上。

    linux查看文件系统块大小与内存页大小

     1)查看文件系统块大小

    /sbin/tune2fs -l /dev/sda1|grep "Block size" 

    2)查看内存页大小

    getconf PAGESIZE

    __get_free_pages
    unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)
    功能:以gfp_mask的方式分配2^order个物理页面
    gfP_mask:分配的方式,指出如何分配在哪分配如GFP_KERNEL
    order:分配2^order个页面
    返回值:返回分配的第一个页的逻辑地址
    头文件: #include <gfp/linux.h>
    
    unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)
    {
        struct page *page;
        VM_BUG_ON((gfp_mask & __GFP_HIGHMEM) != 0);
    
        page = alloc_pages(gfp_mask, order);
        if (!page)
            return 0;
        return (unsigned long) page_address(page);
    }
    void free_pages(unsigned long addr, unsigned int order)->将调用__free_pages()
    功能:释放逻辑地址addr开始的页面2^order次方个
    addr:页面开始的逻辑地址
    order:释放页面的个数2^order个
    头文件: #include <linux/gfp.h>
    
    void free_pages(unsigned long addr, unsigned int order)
    {
        if (addr != 0) {
            VM_BUG_ON(!virt_addr_valid((void *)addr));
            __free_pages(virt_to_page((void *)addr), order);
        }
    }

    例子

    参考引用:

    https://www.cnblogs.com/sky-heaven/p/7390370.html

    https://www.cnblogs.com/wuchanming/p/4465155.html

    https://www.jb51.net/article/97061.htm

    https://www.cnblogs.com/linhaostudy/p/7477370.html

    https://blog.csdn.net/yldfree/article/details/81140022

    https://blog.csdn.net/yafeixi/article/details/70268377

  • 相关阅读:
    POJ 3468 A Simple Problem with Integers
    BZOJ 4430 Guessing Camels
    POJ 2309 BST
    POJ 1990 MooFest
    cf 822B Crossword solving
    cf B. Black Square
    cf 828 A. Restaurant Tables
    Codefroces 822C Hacker, pack your bags!
    [HDU 2255] 奔小康赚大钱
    [BZOJ 1735] Muddy Fields
  • 原文地址:https://www.cnblogs.com/ggzhangxiaochao/p/12893709.html
Copyright © 2011-2022 走看看