LiteOS 内核源码分析:位操作模块
摘要:本文带领大家一起剖析了 LiteOS 位操作模块的源代码,代码非常简单,参考官方示例程序代码,实际编译运行一下,加深理解。
本文分享自华为云社区《LiteOS内核源码分析系列五LiteOS内核源码分析--位操作模块》,原文作者:zhushy 。
在进一步分析之前,本文我们先来熟悉下 LiteOS 提供的辅助功能模块–位操作,在互斥锁等模块对位操作有使用。位操作是指对二进制数的 bit 位进行操作。程序可以设置某一变量为状态字,状态字中的每一 bit 位(标志位)可以具有自定义的含义。文中所涉及的源代码,均可以在 LiteOS 开源站点https://gitee.com/LiteOS/LiteOS 获取。位操作模块源代码、开发文档如下:
LiteOS 内核位操作源代码
位操作模块功能比较简单,包括位操作的头文件 kernel\include\los_bitmap.h、C 源代码文件 kernel\base\los_bitmap.c。
开发指南位操作文档
我们先看看位操作的概念核使用场景,详细的介绍及相关的示例,请参考 LiteOS 开发指南位操作文档。
LiteOS 位操作模块提供对 32 位无符号整数数值的 bit 位操作,bit 位取值为 0-31,以 0 开始计算,从左向右,第 0 位,第 1 位。。。第 31 位等。定义的宏 OS_BITMAP_MASK 如下,也就是十进制 31。如果传入的 bit 为大于 31,会通过逻辑与运算截断(pos& OS_BITMAP_MASK),只取低 5 位,确保不会大于 31,避免溢出。
HuaweiLiteOS 的位操作模块提供标志位的置 1 和清 0 操作,可以改变标志位的内容,同时还提供获取状态字中标志位为 1 的最高位和最低位的功能。用户也可以对系统的寄存器进行位操作。
下面,我们剖析下位操作的源代码。
位操作常用功能
位操作提供了 4 个 API,进行置 1、清 0、获取为 1 的最高、最低位等操作,如下:
LOS_BitmapSet()对状态字的某一标志位进行置 1 操作
对状态字的某一标志位进行置 1 操作。我们先看看传入的参数,需要的 2 个参数分别是:需要改变 bit 位内容的状态字 UINT32 *bitmap,需要改变的 bit 位位数 UINT16 pos。
代码很简单,首先进行基础的校验,如果状态字为空,则返回。然后计算 pos & OS_BITMAP_MASK,只取二进制的低 5 位,最大位值为 31,避免左移的时候发生溢出。1U << (pos & OS_BITMAP_MASK)就是需要改变内容的状态字的 bit 位,通过按位或运算设置状态字 UINT32 *bitmap 的指定 bit 位的内容为 1。
LOS_BitmapClr()对状态字的某一标志位进行清 0 操作
对状态字的某一标志位进行清 0 操作,代码和置 1 操作对应,比较简单,~(1U<< (pos & OS_BITMAP_MASK))表示需要改变内容的状态字的 bit 位为 0,其余位为 1,然后通过按位与运算设置状态字 UINT32 *bitmap 的指定 bit 位的内容为 0。
LOS_HighBitGet()获取状态字中为 1 的最高位
代码中 CLZ(bitmap)是宏,展开为(__builtin_clz(bitmap)),这是编译器内置的高效位运算的库函数,clz 是 count leading zeros 的缩写,就是统计二进制数值中高位区开头的全是 0 的数目。使用 OS_BITMAP_MASK 减去该值,结果就是状态字中的 1 的最高位。
LOS_LowBitGet()获取状态字中为 1 的最低位
代码其中 CLZ(bitmap)是宏,展开为(__builtin_ctz(value)),这是编译器内置的高效位运算的库函数,ctz 是 count trailing zeros 的缩写,就是统计二进制数值中低位区结尾的全是 0 的数目,该结果就是状态字中的 1 的最低位。
小结
本文带领大家一起剖析了 LiteOS 位操作模块的源代码,代码非常简单,参考官方示例程序代码,实际编译运行一下,加深理解。
版权声明: 本文为 InfoQ 作者【华为云开发者社区】的原创文章。
原文链接:【http://xie.infoq.cn/article/8a927fd89b7448949f5d2eb63】。文章转载请联系作者。
评论