find_next_zero_bit and DECLARE_BITMAP

來源:互聯網
上載者:User

find_next_zero_bit:

int find_next_zero_bit

(const unsigned long *addr, int size, int offset)

查詢*addr中,從第offset位開始,第一個不為0的位的位元(最低位從0開始)

,注: offset最小值為0,最大值為sizeof(unsigned long)*8 - 1

//why * 8??

 

sample:

例如尋找位元影像bitmap(共32位)的第5位開始第一個不為0的位的位元(查詢結果為5)
--

5

   4   3   2   1   0

|---|---|---|---|---|---|

0

 | 1 | 1 | 1 | 1 | 1 |            

|---|---|---|---|---|---|   


bitmap = 31 = 011111

---------------------------------------------------------------

#include //Needed by all modules

#include //Needed for KERN_ALERT

int init_module(void)

{

    int devnum;

    unsigned long bitmap = 31;

    devnum = find_next_zero_bit(&bitmap, 32, 5);

    printk("<1> devnum = %d/n", devnum);

    return 0;

}

void cleanup_module(void)

{

    printk(KERN_ALERT "Goodbye./n");

}

 


#define DECLARE_BITMAP(name,bits) /

unsigned long name[BITS_TO_LONGS(bits)]

 

http://blog.chinaunix.net/u1/38994/showart_2002937.html

 

函數原型解析:

 

unsigned long find_next_zero_bit(const unsigned long *addr, unsigned
long size,
        unsigned long offset)
{
    const unsigned
long *p = addr + BITOP_WORD(offset); // offset位於p指向的long地址32位空間
  
 unsigned long result = offset & ~(BITS_PER_LONG-1); //
offset是第result個4位元組
    unsigned long tmp;

    if (offset >=
size)
        return size;
    size -=
result;                                     // 調整32位整倍數上
    offset
%= BITS_PER_LONG;                            // offset位於32位的第幾位
  
 if (offset) {                                       //
offset不在一個long資料的第0位上,在1-31位中[luther.gliethttp]
        tmp = *(p++);
  
     tmp |= ~0UL >> (BITS_PER_LONG - offset);        //
將0-offset資料填充上1.
        if (size <
BITS_PER_LONG)                       // 不足32bits
            goto
found_first;
        if (~tmp)                                      
// 取非非0說明含有0值
            goto found_middle;
        size -=
BITS_PER_LONG;                          //
如果上面~tmp等於0,那麼說明該*p資料為32位全1.[luther.gliethttp]
        result +=
BITS_PER_LONG;
    }
    while (size & ~(BITS_PER_LONG-1))
{                 // 好了,執行到這裡,我們的offset已經處在4位元組的第0位上,下面進行
        if
(~(tmp = *(p++)))                            //
4位元組快速查詢.如果~tmp非0,說明該32位元據中含有0資料,找到.[luther.gliethttp]
          
 goto found_middle;
        result +=
BITS_PER_LONG;                        // 到下一個4位元組空間
        size -=
BITS_PER_LONG;                          // 減少4位元組資料
    }
    if
(!size)                                          //
size等於0,說明首先size等於4位元組整倍數,其次所有資料已經查完,
        return
result;                                  //
所有資料全部為1,沒有發現0位,result等於size.[luther.gliethttp]
    tmp =
*p;                                           //
size不是32位整倍數,還剩幾個bit沒有檢查,繼續執行下面檢查工作.[luther.gliethtp]

found_first:
  
 tmp |= ~0UL << size;                                //
現在0-size為有效資料,size-31為未使用空間,所以先將size-31置成全1.
    if (tmp == ~0UL)  
 /* Are any bits zero? */        // 如果tmp全1,那麼說明就沒找找1個
        return
result + size;    /* Nope. */             //
result+size就等於函數傳入的參數size大小.[luther.gliethttp]
found_middle:
  
 return result + ffz(tmp);                           //
我們在32位元據的0-31中發現必定存在0位值,計算他是第幾位.[luther.gliethttp]
}

#define
ffz(x)  __ffs(~(x))                             //
__ffs找到第一次出現1值的位移值,從bit0開始到bit31依次找[luther.gliethttp]
/**
 * __ffs
- find first bit in word.
 * @word: The word to search
 *
 *
Undefined if no bit exists, so code should check against 0 first.
 */
static
inline unsigned long __ffs(unsigned long word)
{
    int num = 0;

#if
BITS_PER_LONG == 64
    if ((word & 0xffffffff) == 0) {
  
     num += 32;
        word >>= 32;
    }
#endif
  
 if ((word & 0xffff) == 0) {                         //
低16位沒有1值,那麼num加16,同時高16位移動到低16位
        num +=
16;                                      //
這樣低16位永遠都是去掉根本不存在的那種必然情況後的資料.
        word >>= 16;
    }
  
 if ((word & 0xff) == 0) {                           // 低8位是否有
  
     num += 8;
        word >>= 8;
    }
    if ((word
& 0xf) == 0) {
        num += 4;
        word >>= 4;
  
 }
    if ((word & 0x3) == 0) {
        num += 2;
      
 word >>= 2;
    }
    if ((word & 0x1) == 0)
      
 num += 1;
    return num;                                         //
這樣num就是出現1的位移值了.[luther.gliethttp]
}

 

 

 

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.