zoukankan      html  css  js  c++  java
  • 5.16杂记

    linuxc  kmalloc vmalloc malloc区别(转载http://blog.sina.com.cn/s/blog_858820890100ufvy.html)

    kmalloc()和vmalloc()介绍

    kmalloc()

    用于申请较小的、连续的物理内存

    1. 以字节为单位进行分配,在<linux/slab.h>中

    2. void *kmalloc(size_t size, int flags) 分配的内存物理地址上连续,虚拟地址上自然连续

    3. gfp_mask标志:什么时候使用哪种标志?如下:

    ———————————————————————————————-
    情形                          相应标志
    ———————————————————————————————-
    进程上下文,可以睡眠          GFP_KERNEL
    进程上下文,不可以睡眠        GFP_ATOMIC
    中断处理程序                  GFP_ATOMIC
    软中断                        GFP_ATOMIC
    Tasklet                       GFP_ATOMIC
    用于DMA的内存,可以睡眠       GFP_DMA | GFP_KERNEL
    用于DMA的内存,不可以睡眠     GFP_DMA | GFP_ATOMIC
    ———————————————————————————————-

    4. void kfree(const void *ptr)

    释放由kmalloc()分配出来的内存块

    vmalloc()

    用于申请较大的内存空间,虚拟内存是连续的

    1. 以字节为单位进行分配,在<linux/vmalloc.h>中

    2. void *vmalloc(unsigned long size) 分配的内存虚拟地址上连续,物理地址不连续

    3. 一般情况下,只有硬件设备才需要物理地址连续的内存,因为硬件设备往往存在于MMU之外,根本不了解虚拟地址;但为了性能上的考虑,内核中一般使用 kmalloc(),而只有在需要获得大块内存时才使用vmalloc(),例如当模块被动态加载到内核当中时,就把模块装载到由vmalloc()分配 的内存上。

    4.void vfree(void *addr),这个函数可以睡眠,因此不能从中断上下文调用。

    malloc(), vmalloc()和kmalloc()区别

    [*]kmalloc和vmalloc是分配的是内核的内存,malloc分配的是用户的内存

    [*]kmalloc保证分配的内存在物理上是连续的,vmalloc保证的是在虚拟地址空间上的连续,malloc不保证任何东西(这点是自己猜测的,不一定正确)

    [*]kmalloc能分配的大小有限,vmalloc和malloc能分配的大小相对较大

    [*]内存只有在要被DMA访问的时候才需要物理上连续

    [*]vmalloc比kmalloc要慢

    在c语言中实现2进制数字的表示[转载http://hi.baidu.com/chenjihuang/item/11df5bb78d7a2276254b09e0]

    我们知道

    在汇编语言中,16进制的数可以表示为0FH,2进制的数可以表示为00001111B

    在c语言中,16进制的数可以表示为0x0F,但是无法直接表示00001111二进制数

    一、解决方法

    可以用一个宏来解决

    #define BIN(x)                                        
    (                                                                
        ((x)&0x01)                                            |
        (((x/10)&0x01)<<1)&0x02                   |
        (((x/100)&0x01)<<2)&0x04                 |
        (((x/1000)&0x01)<<3)&0x08               |
        (((x/10000)&0x01)<<4)&0x10             |
        (((x/100000)&0x01)<<5)&0x20           |
        (((x/1000000)&0x01)<<6)&0x40         |
        (((x/10000000)&0x01)<<7)&0x80      
    )

    二、例子验证

    这个宏适合8位的二进制数,下面举个例子

    我想表示2进制数10001101

    只须调用宏BIN(10001101),下面在VC6.0上验证过

    /*------------------------test.c start---------------------------------*/

    #include<stdio.h>
    #define BIN(x)                                       
    (                                                            
        ((x)&0x01)                                          |
        (((x/10)&0x01)<<1)&0x02                   |
        (((x/100)&0x01)<<2)&0x04                 |
        (((x/1000)&0x01)<<3)&0x08               |
        (((x/10000)&0x01)<<4)&0x10             |
        (((x/100000)&0x01)<<5)&0x20           |
        (((x/1000000)&0x01)<<6)&0x40         |
        (((x/10000000)&0x01)<<7)&0x80      
    )
    int main(){
    printf("10001011B = %xH ",BIN(10001011));
    return 0;
    }
    /*------------------------test.c end---------------------------------*/   

    显示的结果是

    10001011B = 8b H
    Press any key to continue_

    三、设计思想

    比如10001011,一般情况,编译器将它当成long int类型。

    我们要把每一位是1或者0的情况记录下来

    1.第一次记录最低位,如果是0,转换后的二进制数的最低位也是0,如果是1,转换后的二进制数的最低位也是1。所以,第一句是 (10001011)&0x01 ,使用掩码0x01。如果最低位是0,则结果为0x00;如果最低位是1,则结果是0x01。

    此例中(10001011)&0x01 结果为0x01,二进制为0000 0001

    2.现在记录第二位,有一点要记得,当10001011除以10后,十位数就变成个位数了,而且此时可以用掩码0x01判断,情况同上。可以知道结果是0x01,二进制为0000 0001,但是这应该是在第二位啊!

    简单,在(10001011)&0x01的结果再左移一位,然后形成掩码0x02,主要来判断第二位,即与0x02与。

    因此写成 ( ( (10001011)&0x01 ) << 1 ) & 0x02

    抽象一下 ( ( (x) & 0x01 ) << 1 ) & 0x02

    3.如果是第三位呢?( ( (x) & 0x01 ) << 2 ) & 0x04

    4.依次类推……

    四、不足之处

    1.修改比较麻烦……

    2.如果是00001111,必须写成1111,不然就错了。

    高手如果有什么意见或者改进方法,请留言o(∩_∩)o...

    五、改进

    主要是对问题的第二点

    #define BIN(x)   
    (                                     
        ((1x)&0x01)                                          |
        (((1x/10)&0x01)<<1)&0x02                   |
        (((1x/100)&0x01)<<2)&0x04                 |
        (((1x/1000)&0x01)<<3)&0x08               |
        (((1x/10000)&0x01)<<4)&0x10             |
        (((1x/100000)&0x01)<<5)&0x20           |
        (((1x/1000000)&0x01)<<6)&0x40         |
        (((1x/10000000)&0x01)<<7)&0x80      
    )

    在宏定义中的x中前加1

    这个我就不解释,理解的关键是在于是否清楚编译程序的过程,对宏的处理

    这个可以去查看相关的书籍

  • 相关阅读:
    添加unique约束
    设置自增列的步长和起始值
    创建外键及主键
    绘制折线图和叠加区域图
    绘制饼图
    生成叠加柱状图和水平柱状图
    随机生成带有颜色的验证码
    os模块与操作系统的交互
    TDate赋值给Variant时注意的问题
    线程中的异常处理
  • 原文地址:https://www.cnblogs.com/liu-bei/p/3732808.html
Copyright © 2011-2022 走看看