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。
- 开发指南位操作文档
在线文档https://gitee.com/LiteOS/LiteOS/blob/master/doc/LiteOS_Kernel_Developer_Guide.md#%E4%BD%8D%E6%93%8D%E4%BD%9C。
我们先看看位操作的概念核使用场景,详细的介绍及相关的示例,请参考LiteOS开发指南位操作文档。
LiteOS位操作模块提供对32位无符号整数数值的bit位操作,bit位取值为0-31,以0开始计算,从左向右,第0位,第1位。。。第31位等。定义的宏OS_BITMAP_MASK如下,也就是十进制31。如果传入的bit为大于31,会通过逻辑与运算截断(pos & OS_BITMAP_MASK),只取低5位,确保不会大于31,避免溢出。
#define OS_BITMAP_MASK 0x1FU
Huawei LiteOS的位操作模块提供标志位的置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。
VOID LOS_BitmapSet(UINT32 *bitmap, UINT16 pos)
{
if (bitmap == NULL) {
return;
}
*bitmap |= 1U << (pos & OS_BITMAP_MASK);
}
LOS_BitmapClr()对状态字的某一标志位进行清0操作
对状态字的某一标志位进行清0操作,代码和置1操作对应,比较简单,~(1U << (pos & OS_BITMAP_MASK))表示需要改变内容的状态字的bit位为0,其余位为1,然后通过按位与运算设置状态字UINT32 *bitmap的指定bit位的内容为0。
VOID LOS_BitmapClr(UINT32 *bitmap, UINT16 pos)
{
if (bitmap == NULL) {
return;
}
*bitmap &= ~(1U << (pos & OS_BITMAP_MASK));
}
LOS_HighBitGet()获取状态字中为1的最高位
代码中CLZ(bitmap)是宏,展开为(__builtin_clz(bitmap)),这是编译器内置的高效位运算的库函数,clz是count leading zeros的缩写,就是统计二进制数值中高位区开头的全是0的数目。使用OS_BITMAP_MASK减去该值,结果就是状态字中的1的最高位。
UINT16 LOS_HighBitGet(UINT32 bitmap)
{
if (bitmap == 0) {
return LOS_INVALID_BIT_INDEX;
}
return (OS_BITMAP_MASK - CLZ(bitmap));
}
LOS_LowBitGet()获取状态字中为1的最低位
代码其中CLZ(bitmap)是宏,展开为(__builtin_ctz(value)),这是编译器内置的高效位运算的库函数,ctz是count trailing zeros的缩写,就是统计二进制数值中低位区结尾的全是0的数目,该结果就是状态字中的1的最低位。
UINT16 LOS_LowBitGet(UINT32 bitmap)
{
if (bitmap == 0) {
return LOS_INVALID_BIT_INDEX;
}
return CTZ(bitmap);
}
小结
本文带领大家一起剖析了LiteOS位操作模块的源代码,代码非常简单,参考官方示例程序代码,实际编译运行一下,加深理解。
相关文章
- Postgresql源码(66)insert on conflict语法介绍与内核执行流程解析
- Linux内核版本查看_mysql隐藏版本号
- “土法”排查与修复一个 Linux 内核 Bug
- CentOS 6.5 获取内核源码
- 【Linux 内核】Linux 内核源码根目录下的文件 ( .clang-format | COPYING | CREDITS | Kbuild | Kconfig | MAINTAINERS )
- 【Linux 内核】进程管理 ( 内核线程概念 | 内核线程、普通进程、用户线程 | 内核线程与普通进程区别 | 内核线程主要用途 | 内核线程创建函数 kernel_thread 源码 )
- 【Linux 内核】CFS 调度器 ⑤ ( CFS 调度器类 fair_sched_class 源码 | next 赋值 | enqueue_task 赋值 | dequeue_task 赋值 )
- 【Linux 内核 内存管理】mmap 系统调用源码分析 ④ ( do_mmap 函数执行流程 | do_mmap 函数源码 )
- 【Linux 内核 内存管理】memblock 分配器编程接口 ① ( memblock 分配器编程接口简介 | memblock_add 函数原型分析 | memblock_add 函数源码 )
- Linux内核:占用系统内存的分析(linux内核占用内存)
- 分析Linux内核日志:Kmsg技术指南(linuxkmsg)
- 了解Linux各版本特性:从发行版到内核版(linux的版本有哪些)
- 加载Linux内核:KO文件加载技术指南(linuxko文件)
- Ubuntu 18.04 LTS 整合Livepatch:安装Linux内核后无需重启
- Linux内核配置:从配置文件开始(linux内核配置文件)
- 深入Linux内核:构建与调试源码(linux源码调试)
- LINUX下安装内核源码现场实操(linux安装内核源代码)
- 深入浅出Linux内核源码学习(linux内核源码学习)
- 深入Linux内核源码分析之旅(linux内核源码分析)
- Linux如何获取内核源码?(linux获取内核源码)
- Linux 内核消息两则: 4.5 发布,历史最悠久的 LTS 内核 2.6.32 终止支持
- Linux 内核开发人员考虑剔除对更多老旧平台的处理器支持
- 深度探索Linux源码版本:解密内核奥秘(linux源码版本)
- 深入剖析Linux内核:源码阅读器(linux源码阅读器)
- 利用Linux内核SCTP技术保障网络稳定性(linuxsctp)
- kernelLinux 3.8内核引领新技术革新(linux3.8)
- 深度探究:Linux内核源码剖析(linux内核源码剖析)