核心中bitmap的使用

lxgeek發表於2014-11-08

  在編寫應用層程式碼中使用點陣圖,發現核心中已經有現成的實現便使用之。對點陣圖的使用主要是幾個

關鍵API。

 

第一:bitmap_zero函式用於初始化點陣圖

原始碼如下:

/*
 *@dst: 點陣圖的起始地址
 *@nbits: 點陣圖的個數
 */
static inline void bitmap_zero(unsigned long *dst, int nbits)
{
    int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
        memset(dst, 0, len);
}

 

第二:bitmap_set函式用於設定特定的位

 1 /*
 2  * @map: 點陣圖的記憶體空間的首地址
 3  * @start:需要設定的起始位
 4  * @nr : 需要設定的位的數目  
 5 */
 6 void bitmap_set(unsigned long *map, int start, int nr)
 7 {
 8     unsigned long *p = map + BIT_WORD(start);   //以unsigned long 為單位的情況,設定起始位置
 9     const int size = start + nr;  //需要設定的末位,不包括此位    
10     /*
11      * @bits_to_set 在一個需要設定的unsigned long中,可能需要設定的位
12      * [0_____start_________BITS_PER_LONG)
13      *                [0____________________bits_to_set) 
14      */
15     int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);    
16     unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start); 
17    
18     while (nr - bits_to_set >= 0) {
19         *p |= mask_to_set;
20         nr -= bits_to_set;    
21         bits_to_set = BITS_PER_LONG; //經過上一步的操作後,需要設定的位都是BITS_PER_LONG的倍數 
22         mask_to_set = ~0UL;
23         p++;
24     }
25     if (nr) {  //nr 必須大於1,此函式才有效果
26         mask_to_set &= BITMAP_LAST_WORD_MASK(size);
27         *p |= mask_to_set;  //產生最終的效果
28     }
29 }

 

與bit_set函式相對應的是bit_clear函式用於清除位,其實現原理和bit_set函式類似。

 

第三:find_first_zero_bit函式用於找到第一個清空位

/*
* Find the first cleared bit in a memory region.
* @addr: 點陣圖的起始位置
* @size: 點陣圖的大小
*/
unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size)
{
    const unsigned long *p = addr;
    unsigned long result = 0;
    unsigned long tmp;

    while (size & ~(BITS_PER_LONG-1)) {        //點陣圖的大小超過一個 BIT_PER_LONG的情況下
        if (~(tmp = *(p++)))
            goto found;
        result += BITS_PER_LONG;
        size -= BITS_PER_LONG;
    }
    if (!size)   //此情況成立的時候,也是沒有找到。且size應該是 BIT_PER_LONG的整數倍。
        return result; 
       
    tmp = (*p) | (~0UL << size);      
    if (tmp == ~0UL)    /* Are any bits zero? */
        return result + size;   /* Nope. */      //如果沒有找到就會返回 size
found:
    return result + ffz(tmp);
}  

 

於此函式對應的是函式find_first_bit尋找第一個設定位。

 

第四:find_next_zero_bit 和 find_next_bit 函式可以在第一次找到後,再次尋找清空位或設定位。

 

具體使用情況可以參考:

核心模組

應用層程式

 

備註:

點陣圖除了應用於記憶體管理,還可以應用到對共享資源的管理,LDD3的P128就有提到。

 

相關文章