-------------------------------------------
本文系作者原创, 欢迎大家转载!
转载请注明出处: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。
 

linux tricks 之 bitmap分析.的更多相关文章

  1. 网易视频云技术分享:linux软raid的bitmap分析

    网易视频云是网易倾力打造的一款基于云计算的分布式多媒体处理集群和专业音视频技术,提供稳定流畅.低时延.高并发的视频直播.录制.存储.转码及点播等音视频的PAAS服务,在线教育.远程医疗.娱乐秀场.在线 ...

  2. Linux内核源代码情景分析系列

    http://blog.sina.com.cn/s/blog_6b94d5680101vfqv.html Linux内核源代码情景分析---第五章 文件系统  5.1 概述 构成一个操作系统最重要的就 ...

  3. Linux内核源码分析之setup_arch (四)

    前言 Linux内核源码分析之setup_arch (三) 基本上把setup_arch主要的函数都分析了,由于距离上一篇时间比较久了,所以这里重新贴一下大致的流程图,本文主要分析的是bootmem_ ...

  4. Android/Linux下CGroup框架分析及其使用

    1 cgroup介绍 CGroup是control group的简称,它为Linux kernel提供一种任务聚集和划分的机制,可以限制.记录.隔离进程组(process groups)所使用的资源( ...

  5. Linux Kernel Oops异常分析

    1.PowerPC小系统内核异常分析 1.1  异常打印 Unable to handle kernel paging request for data at address 0x36fef31eFa ...

  6. 20169212《Linux内核原理与分析》课程总结

    20169212<Linux内核原理与分析>课程总结 每周作业链接汇总 第一周作业:完成linux基础入门实验,了解一些基础的命令操作. 第二周作业:学习MOOC课程--计算机是如何工作的 ...

  7. 1.linux服务器的性能分析与优化

    [教程主题]:1.linux服务器的性能分析与优化 [课程录制]: 创E [主要内容] [1]影响Linux服务器性能的因素 操作系统级 CPU 目前大部分CPU在同一时间只能运行一个线程,超线程的处 ...

  8. 20169212《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 这一周学习了MOOCLinux内核分析的第一讲,计算机是如何工作的?由于本科对相关知识的不熟悉,所以感觉有的知识理解起来了有一定的难度,不过多查查资 ...

  9. Linux系统日志及日志分析

    Linux系统日志及日志分析   Linux系统拥有非常灵活和强大的日志功能,可以保存几乎所有的操作记录,并可以从中检索出我们需要的信息. 大部分Linux发行版默认的日志守护进程为 syslog,位 ...

随机推荐

  1. 终端terminal配色

    切换到~/.bash_profile,无此.bash_profile文件可创建 在文件内粘入以下代码: #enables colorin the terminal bash shell export ...

  2. ASP+ACCESS手工注入详解

    SQL注入这么长时间,看见有的朋友还是不会手工注入,那么我来演示一下.高手略过. 我们大家知道,一般注入产生在没经过虑的变量上,像ID?=XX这样的. 下面以这个网址为例: http://zsb.xx ...

  3. WEB移动应用框架构想(转载)

    iUI.jQTouch.WPTouch.PhoneGap.XUI.iWebkit.Rhodes.gwt-mobile…当我们已经开始惊 叹 web移动应用充斥着各种各样框架与类库的时候,其实各大web ...

  4. 利用memcached构建高性能的Web应用程序(转载)

    面临的问题 对于高并发高访问的Web应用程序来说,数据库存取瓶颈一直是个令人头疼的问题.特别当你的程序架构还是建立在单数据库模式,而一个数据池连接数峰 值已经达到500的时候,那你的程序运行离崩溃的边 ...

  5. 修改linux最大文件句柄数

    大家知道在linux服务器大并发调优时,往往需要预先调优linux参数,其中修改linux最大文件句柄数是最常修改的参数之一. 在linux中执行ulimit -a 即可查询linux相关的参数,如下 ...

  6. ubuntu快速清理磁盘垃圾

    .快速清理磁盘垃圾 磁盘空间又不够用了?尝试在终端窗口中输入sudo apt-get autoremove然后输入sudo apt-get clean,前一个命令会卸载系统中所有未被使用的依赖关系,后 ...

  7. javascript判断上传文件大小

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. jsp include page指令标记

    include指令标记 <jsp:include page=""> 父页面和包含进来的页面单独编译,单独翻译成servlet后,在前台拼成一个HTML页面. 动态编译& ...

  9. 获取并设置ListView高度的方法

    01 public void setListViewHeightBasedOnChildren(ListView listView) {  02     ListAdapter listAdapter ...

  10. sizeof()和strlen()的区别与联系

    参考:http://www.cnblogs.com/carekee/articles/1630789.html 1.sizeof是运算符,其值在编译时即计算好了,参数可以是数组.指针.类型.对象.函数 ...