5.16雜記

linux\c  kmalloc vmalloc malloc區別(轉載http://blog.sina.com.cn/s/blog_858820890100ufvy.html)

kmalloc()和vmalloc()介紹html

kmalloc()linux

用於申請較小的、連續的物理內存函數

1. 以字節爲單位進行分配,在<linux/slab.h>中性能

2. void *kmalloc(size_t size, int flags) 分配的內存物理地址上連續,虛擬地址上天然連續spa

3. gfp_mask標誌:何時使用哪一種標誌?以下:設計

———————————————————————————————-
情形                          相應標誌
———————————————————————————————-
進程上下文,能夠睡眠          GFP_KERNEL
進程上下文,不能夠睡眠        GFP_ATOMIC
中斷處理程序                  GFP_ATOMIC
軟中斷                        GFP_ATOMIC
Tasklet                       GFP_ATOMIC
用於DMA的內存,能夠睡眠       GFP_DMA | GFP_KERNEL
用於DMA的內存,不能夠睡眠     GFP_DMA | GFP_ATOMIC
———————————————————————————————-htm

4. void kfree(const void *ptr)blog

釋放由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二進制數

1、解決方法

能夠用一個宏來解決

#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       \
)

2、例子驗證

這個宏適合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 \n",BIN(10001011));
return 0;
}
/*------------------------test.c end---------------------------------*/   

顯示的結果是

10001011B = 8b H
Press any key to continue_

3、設計思想

好比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.依次類推……

4、不足之處

1.修改比較麻煩……

2.若是是00001111,必須寫成1111,否則就錯了。

 

高手若是有什麼意見或者改進方法,請留言o(∩_∩)o...

5、改進

主要是對問題的第二點

#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

這個我就不解釋,理解的關鍵是在因而否清楚編譯程序的過程,對宏的處理

這個能夠去查看相關的書籍

相關文章
相關標籤/搜索