内核中常用的bit操作

5620阅读 0评论2016-04-17 wibnmo
分类:LINUX

1. set_bit/clear_bit


set_bit(nr,addr)将addr的第nr位置1

clear_bit(nr,addr)


test_and_set_bit(nr,addr)将addr的第nr位置1,并返回原始addr第nr位的值

test_and_clear_bit(nr,addr)


在内核中有好几处实现,不过大同小异,我们看两种:

include/asm-generic/bitops/atomic.h

static inline void set_bit(int nr, volatile unsigned long *addr)

{

        unsigned long mask = BIT_MASK(nr);

        unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);//这里为什么这么做,不太明白

        unsigned long flags;                                                                                                  


        _atomic_spin_lock_irqsave(p, flags);

        *p  |= mask;

        _atomic_spin_unlock_irqrestore(p, flags);

}


include/linux/bitops.h

#define BIT_MASK(nr)            (1UL << ((nr) % BITS_PER_LONG))

#define BIT_WORD(nr)            ((nr) / BITS_PER_LONG)


arch/arm/include/asm/types.h

#define BITS_PER_LONG 32


比如BIT_MASK(3) = (1UL << ((3) % 32)) = 0x8(1000)


另一种实现:

arch/arm/include/asm/bitops.h

static inline int

____atomic_test_and_set_bit(unsigned int bit, volatile unsigned long *p)

{

        unsigned long flags;

        unsigned int res;

        unsigned long mask = 1UL << (bit & 31); //和上面的mask方式不同的是这里用的逻辑与


        p += bit >> 5;  //不太明白为什么要这么做


        raw_local_irq_save(flags);

        res = *p;

        *p = res | mask;

        raw_local_irq_restore(flags);


        return (res & mask) != 0;

}


还有一种是用汇编实现的,不贴了。


关键要注意的是这种用法,比如取mask的方法:

mask = 1UL << (bit & 31)

mask = (1UL << ((nr) % BITS_PER_LONG))


从这里我们可以看出,整除和逻辑与的作用是一样的。


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

2. BITS_TO_LONGS


它的作用就是看一个数含有几个long的长度


include/linux/bitops.h

#define BITS_TO_LONGS(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))

#define BITS_PER_BYTE           8


include/linux/kernel.h

#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))



比方BITS_TO_LONGS(33) DIV_ROUND_UP(33, 8 * 4)


DIV_ROUND_UP(33, 8 * 4) (((33) + (32) - 1) / (32)) 即 2


也就是33含有2个long的长度



上一篇:如何在嵌入式设备上跑自己的程序
下一篇:抬头纹和颜色饱和度不够解析手法