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

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

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

原文地址:https://www.cnblogs.com/liu-bei/p/3732808.html