开源代码赏析之find_next_bit函数
1 函数功能
假定unsigned long数组addr有n个元素,则其可以表示n*sizeof(unsignedlong)*8个bit位。find_next_bit可以找到从第offset个bit位开始、在offset~size区间的第一个值为1的bit位位置,如果没有找到满足条件的bit位则返回最大尺寸size。
2 函数原型
/*
*@brief\
* 在addr表示的bit位图数组中,查找offset~size区间中第一个1bit位的索引值
*@input\
* addr: unsigned long数组,每个元素表示sizeof(unsigned long)*8个bit位
* size: 查找结束位置
* offset:查询起始位置
*/
unsigned long find_next_bit(constunsignedlong*addr, unsignedlongsize,unsignedlongoffset)
3 实现逻辑
图1 unsigned long数组表示的bit位图(64位系统)
如图1所示,addr数组中的每一个元素表示64个bit位,每一个元素按低位向高位依次进行排列。n个数可表示的最大bit位个数为n* sizeof(unsigned long)*8,即64*n。根据上图可以看出:最大尺寸size可以是1~64n之间的任意值,而起始偏移值为0~size之间的任意值。针对size和offset不同的可能取值,有以下几种情况:
(1)、size为size_1,即最大尺寸不是BITS_PER_LONG的整数倍,这表明数组addr的最后一个元素中部分高bit位没有使用,在处理的时候需要考虑到这种情况;
(2)、size为size_2,即最大尺寸为BITS_PER_LONG的整数倍,则不存在(1)中描述的无效bit位;
(3)、起始索引值offse为offset_1或offset_3,即offset是BITS_PER_LONG的整数倍;
(4)、起始索引值offse为offset_2或offset_4,即offset不是BITS_PER_LONG的整数倍;
针对上面的情况,下面进行具体分析:
(a)、首先,找到起始索引offset所在的元素,即:addr[j]= addr+offset/BITS_PER_LONG,则已跳过的元素中包含的bit位个数为:(offset/BITS_PER_LONG)*BITS_PER_LONG。处理将从该元素的第offset% BITS_PER_LONG个bit位开始。
(b)、假定offset为offset_4,则当前元素是最后一个元素,只需要从offset_4%BITS_PER_LONG到BITS_PER_LONG-1位依次比较,找出第一个1bit位即可。但当size为size_1时,addr[n-1]中存在BITS_PER_LONG-size_1% BITS_PER_LONG个无效的bit位;因此,在比较最后一个元素时,需要置高位的BITS_PER_LONG-size_1%BITS_PER_LONG个无效bit位和低位已跳过的offset_4%BITS_PER_LONG个bit位为0。
(c)、假定offset为offset_2,则当前元素不是最后一个元素,且当前元素中不可能存在无效的bit位。因此,只需要取出当前元素,跳过当前元素中的offset_2%BITS_PER_LONG个低位bit位后逐个比较bit位。如果找到了bit位1就直接返回其索引