Linux kernel中 __bitmap_weight函数的理解
来源:互联网 发布:大数据安全分析 编辑:程序博客网 时间:2024/05/21 12:29
对Linux kernel中 __bitmap_weight函数的理解
int __bitmap_weight(const unsigned long *bitmap, int bits){int k, w = 0, lim = bits/BITS_PER_LONG;for (k = 0; k < lim; k++)w += hweight_long(bitmap[k]);if (bits % BITS_PER_LONG)w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));return w;}
static inline unsigned long hweight_long(unsigned long w){return sizeof(w) == 4 ? hweight32(w) : hweight64(w);}
hweight32函数和hweigh64函数是一样的/**
* hweightN - returns the hamming weight of a N-bit word
* @x: the word to weigh
*
* The Hamming Weight of a number is the total number of bits set in it.
*/
求32位二进制数中的'1'的个数:
static inline unsigned int hweight32(unsigned int w)
{
unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
}
分析:
这个函数的目的是求32位二进制数中的'1'的个数,我认为主要用到的思想就是算法中的"分治法"。以最为极端的情况来考虑
即w = 0xFFFFFFFF。
1).unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
这里需要注意一点:w的类型为unsigned int(无符号整型,32位),因此,当w左移时,无论w的最高位是否为1,高位都用0补充。
w = 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 UL
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
[array32] 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
res = ( 0xFFFFFFFF & 0x55555555 ) + ( ( 0xFFFFFFFF >> 1 ) & 0x55555555 )
= 0x55555555 + ( 0x7FFFFFFF & 0x55555555 )
= 0x55555555 + 0x55555555
= 0xAAAAAAAA
= 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 UL
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
[array16] 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
[array]是我为这个32位数标注的组号。
w当然就是一个有32个元素的组,我的目的不是要找到这32个元素中有多少个"1"么?好了,这里用到的最重要的思想就是:相邻组相加!!注意相邻组不是相邻位。第一次,相邻组就是1+2,3+4,5+6,... 31+32,这样加过来就从array32变成了array16了,函数的第一条语句相当于执行了16个运算!!!!
这里用图表示会更加形象:
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
w = 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 UL
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
[array32] 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
->+| ->+| ->+| ->+| ->+| ->+| ->+| ->+| ->+| ->+| ->+| ->+| ->+| ->+| ->+| ->+|
V V V V V V V V V V V V V V V V
---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
res =1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 UL
---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
[array16] 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
2). 如此将数组维度继续缩小,相邻组相加,这次是1+2, 3+4, 5+6, ... 15+16,这样将array16变为array8... 直到array中只剩下一个元素,所有的"1"就都加在了一起。
如图所示:
---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
res = 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 UL
---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
[array16] 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
| | | | | | | | | | | | | | | |
-->+| -->+| --->+| -->+| -->+| --->+| -->+| --->+|
V V V V V V V V
---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- --
res = 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 UL
---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- --
[array8] 8 7 6 5 4 3 2 1
| | | | | | | |
--------->+| --------->+| --------->+| --------->+|
V V V V
------------------------- ------------------------ ------------------------ ------------------------ --
res = 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 UL
------------------------- ------------------------ ------------------------ ------------------------ --
[array4] 4 3 2 1
| | | |
---------------------->+| ----------------------->+|
V V
-------------------------------------------------- --------------------------------------------------- --
res = 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 UL
-------------------------------------------------- --------------------------------------------------- --
[array2] 2 1
| |
--------------------------------------------------->+|
V
------------------------------------------------------------------------------------------------------ --
res = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 UL
------------------------------------------------------------------------------------------------------ --
[array1] 1
|
V
32
这样一来,五条语句相当于执行了16+8+4+2+1 = 31个运算了!!!!
下面是我自己写的一个模仿程序,以验证这个算法。该程序找到一个无符号8位数中"1"的个数
#include <stdio.h>
#include <linux/types.h>
static int my_hweight8( __u8 w )
{
__u8 ret = ( w & 0x55 ) + ( ( w >> 1 ) & 0x55 );
ret = ( ret & 0x33 ) + ( ( ret >> 2 ) & 0x33 );
ret = ( ret & 0x0F ) + ( ( ret >> 4 ) & 0x0F );
return (int)ret;
}__attribute__((always_inline))
int main()
{
int get_hweight8 = my_hweight8(0x6D);
printf("there are %d '1' in my 0x6D/n", get_hweight8);
return 0;
}
- Linux kernel中 __bitmap_weight函数的理解
- 对Linux kernel中 generic_hweight32函数的理解
- 对Linux kernel中 generic_hweight32函数的理解
- ns3中linux kernel的位置理解
- linux kernel 2.4.16 __alloc_bootmem_core函数的理解
- 对Kernel函数的理解
- linux kernel中typeof和container_of的理解
- 理解linux kernel的一些文档文献
- Linux kernel内核架构的理解
- Linux中IS_ERR()函数的理解
- Linux中IS_ERR()函数的理解
- linux中mmap函数的理解
- 深入理解Linux kernel(内核)中的signal函数
- 深入理解Linux kernel(内核)中的signal函数
- linux kernel的函数与抽象层
- linux kernel协议处理函数的组织
- 在linux kernel中打印函数调用的堆栈的方法
- linux kernel initcall函数
- 大数据处理实例——Amazon商品评分&评论(一)
- AngularJS学习之 ng-route模块
- XHTML笔记
- ubuntu 配置Android环境
- Tornado配置/使用小小心得
- Linux kernel中 __bitmap_weight函数的理解
- 第45篇 WebRTC及点阵笔研究(八)
- 【LightOJ 1307 + 二分】
- noi2015软件包管理器
- 利用Struts2框架,将后台数据转化为JSON数据并返回到前台
- TCP/IP模型小结
- 多版本Python共存时pip给指定版本的python安装package的方法
- 深入理解C#---1.可空类型
- DefaultKeyedVector和KeyedVector用法