find_next_zero_bit and DECLARE_BITMAP

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]
}

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值