-------------------------------------------
本文系作者原创, 欢迎大家转载!
转载请注明出处:netwalker.blog.chinaunix.net
-------------------------------------------
通过位图提供的两种状态可以在非常节约内存的情况下表示开关变量,并且同类这类变量可以紧凑而高效的统一进行处理。有很多内核子系统都需要位图的支持,但是不同的情况又需要不同的位图个数,比如SMP系统上的CPU位图cpumask的位数位NR_CPUS,而内存管理区的位图数为MAX_ZONES_PER_ZONELIST。但是所有的位图都要转换为基本的数据类型,比如int,short等,Linux将定义位图的功能集中到一个名为DECLARE_BITMAP的宏。
 include/linux/types.h
#define DECLARE_BITMAP(name,bits) \
unsigned long name[BITS_TO_LONGS(bits)]

这里可以看到DECLARE_BITMAP的作用是尝试定义一个类型为unsigned long,名字为name的数组。而数组的维度由位图中的位数通过BITS_TO_LONGS计算而得。

 include/linux/bitops.h
#define BITS_PER_BYTE 8
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))

BITS_TO_LONGS通过DIV_ROUND_UP宏完成。DIV_ROUND_UP根据nr参数计算至少需要几个long型才能满足当前位图的需求。不知道为什么Linux不使用char型,这样不是更节约内存吗?显然DECLARE_BITMAP的引入的根本目的并不是用来节约内存,而是方便对长位图的操作,而通常8位位图的定义并不通过它来定义,而是直接定义位掩码,比如对文件权限的定义。

内核定义了一系列的宏和函数来对DECLARE_BITMAP定义的位图进行操作,它们分别位于bitmap.h和bitmap.c中。这些宏和函数的操作思想是一致的。

 /arch/arm/include/asm/types.h
#define BITS_PER_LONG 32 include/linux/bitmap.h
static inline void bitmap_zero(unsigned long *dst, int nbits)
{
if (nbits <= BITS_PER_LONG)
*dst = 0UL;
else {
int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
memset(dst, , len);
}
}

尽管在特定体系的代码中BITS_PER_LONG被定义为32以增加运算速度,但是它更应该通过sizeof(long) * BITS_PER_BYTE来定义。bitmap_zero用来清空所有的位图。分析它发现,它首先判断是否超过一个long型,如果没有那么直接对它赋值0UL即可。否则就要通过memset对整个数组进行操作。其他函数亦同。一些常用的位图操作函数如下所示:

  • bitmap_zero 清所有比特位为0,被用来初始化位图。圆整到unsigned long。
  • bitmap_fill 置nbits指定个数的比特位为1。精确到位。
  • bitmap_copy 从src复制所有比特位到dst。圆整到unsigned long。
  • bitmap_and 将nbits指定的位数按位与结果存放到dst。圆整到unsigned long。
  • bitmap_or 将nbits指定的位数按位或结果存放到dst。圆整到unsigned long。
  • bitmap_xor 将nbits指定的位数按位异或结果存放到dst。圆整到unsigned long。
  • bitmap_andnot 根据nbits指定的位数, 将src1按位与上src2的按位非,结果存放到dst。圆整到unsigned long。
  • bitmap_complement 根据nbits指定的位数, 按位取反后存放到dst。精确到位。
  • bitmap_equal 比较nbits指定的位数,如果这些为全部相同返回1,否则返回0。精确到位。
  • bitmap_intersects 比较nbits指定的位数中是否有重合(相交Overlap)的1比特位,也即src1和src2中有共同设置为1的标志位。有则返回1,否则返回0。精确到位。
  • bitmap_subset src1的nbits指定位数中设置1的比特位是src2中nbits指定位数中设置1的比特的子集,则返回1,否则返回0。精确到位。
  • bitmap_empty 测试src中的低nbits位是否全为0,是则返回1,否则返回0。精确到位。
  • bitmap_full 测试src中的低nbits位是否全为1,是则返回1,否则返回0。精确到位。
  • bitmap_weight 返回低nbits位的汉明重量(Hamming Weight)。
  • bitmap_shift_right 逻辑右移n位,左边补0。n可以大于nbits数。圆整到unsigned long。
  • bitmap_shift_left 逻辑左移n位,右边补0。n可以大于nbits数。圆整到unsigned long。
 

最新文章

  1. JQuery 滚动条插件perfect-scrollbar
  2. 使用TopSelf创建自宿主的Windows服务程序
  3. [已解决]从微软合作伙伴资源和MSDN下载系统和软件Microsoft download Manager无效
  4. java-map和object装换
  5. windows下制作PHP扩展
  6. [Flex] IFrame系列 —— 嵌入本地页面两种方式source和content(html页面和html代码)
  7. js利用数组length属性清空和截短数组
  8. 【转】强大的vim配置文件,让编程更随意
  9. 应付配置文件 Profile
  10. 嵌入式开发软件环境:uboot、kernel、rootfs、data布局分析
  11. POJ_3685_Matrix_(二分,查找第k大的值)
  12. Java设计模式(学习整理)---适配模式
  13. listview滚动到底部
  14. Tiny6410之LED裸机驱动
  15. SPFA中 正逆邻接表的建立
  16. ll 和 ls -l的详解
  17. Bootstrap常用样板
  18. MySQL数据库之auto_increment【转】
  19. python截图
  20. Spark学习笔记——键值对操作

热门文章

  1. block中防止循环引用的一个高大上的宏定义
  2. struts2 + ajax + json的结合使用,实例讲解
  3. 统一软件开发过程(rup)理解
  4. Swift翻译之-Swift语法入门 Swift语法介绍
  5. tolua.cast的实用方法
  6. 测试Swift语言代码高亮-使用highlight.js
  7. Linux 4.6分支已到生命尽头 请尽快升级至Linux 4.7.1
  8. 高流量站点NGINX与PHP-fpm配置优化
  9. IOS 使用横屏
  10. hiho一下 第九十五周 数论四&#183;扩展欧几里德