[Linux]学习笔记系列 -- bits


title: bits

categories:

  • linux
  • include
    tags:
  • linux
  • include
    abbrlink: 75328c4f
    date: 2025-10-03 09:01:49

https://github.com/wdfk-prog/linux-study

文章目录

  • include/linux/bits.h
    • [BIT_WORD 位图的字数](#BIT_WORD 位图的字数)
  • include/linux/bitmap.h
    • [bitmap_weight 位图的权重](#bitmap_weight 位图的权重)
  • include/linux/bitops.h
    • bitop
    • [test_bit 用于测试某个位是否被设置(即是否为 1)](#test_bit 用于测试某个位是否被设置(即是否为 1))
    • [assign_bit 为内存中的位分配值](#assign_bit 为内存中的位分配值)
    • fls_long
    • [BITS_TO_LONGS 位图的字数](#BITS_TO_LONGS 位图的字数)

include/linux/bits.h

BIT_WORD 位图的字数

c 复制代码
//include/asm-generic/bitsperlong.h
#ifdef CONFIG_64BIT
#define BITS_PER_LONG 64
#else
#define BITS_PER_LONG 32
#endif /* CONFIG_64BIT */

#define BIT_WORD(nr)		((nr) / BITS_PER_LONG)

include/linux/bitmap.h

bitmap_weight 位图的权重

  • 用于计算位图(bitmap)中设置为 1 的位的数量(即权重)
c 复制代码
static __always_inline
unsigned int bitmap_weight(const unsigned long *src, unsigned int nbits)
{
	if (small_const_nbits(nbits))
		return hweight_long(*src & BITMAP_LAST_WORD_MASK(nbits));
	return __bitmap_weight(src, nbits);
}

include/linux/bitops.h

bitop

c 复制代码
/* 许多特定于体系结构的非原子 Bitops 包含内联 asm 代码,因此编译器无法将它们优化为编译时表达式或常量。
相反,generic_*() 辅助函数是用纯 C 语言定义的,编译器对它们进行了优化。
为了在某些情况下(如参数是编译时常量时)利用这种优化,bitop 宏会选择通用的 C 实现(如 const##op),而在其他情况下则使用默认的实现(如 op)。这种设计使得代码在性能敏感的场景中既能保持高效,又能在编译时优化常量表达式。
从 .bss 或 .data 传递位图时,需要强制转换到"uintptr_t"以缓解"-Waddress"警告 (-> '!!addr' 始终为 true)。
 */
#define bitop(op, nr, addr)						\
	((__builtin_constant_p(nr) &&					\
	  __builtin_constant_p((uintptr_t)(addr) != (uintptr_t)NULL) &&	\	//检查 addr 是否是一个非空的编译时常量地址
	  (uintptr_t)(addr) != (uintptr_t)NULL &&			\				//检查 addr 是否为非空指针
	  __builtin_constant_p(*(const unsigned long *)(addr))) ?	\		//检查 addr 指向的值是否是一个编译时常量
	 const##op(nr, addr) : op(nr, addr))								//如果所有条件都满足(即 nr、addr 和 *addr 都是编译时常量),宏会调用 const##op(nr, addr)。否则使用通用实现

test_bit 用于测试某个位是否被设置(即是否为 1)

c 复制代码
#define test_bit(nr, addr)		bitop(_test_bit, nr, addr)

assign_bit 为内存中的位分配值

c 复制代码
/**
 * assign_bit - Assign value to a bit in memory
 * @nr: the bit to set
 * @addr: the address to start counting from
 * @value: the value to assign
 */
#define assign_bit(nr, addr, value)					\
	((value) ? set_bit((nr), (addr)) : clear_bit((nr), (addr)))

#define __assign_bit(nr, addr, value)					\
	((value) ? __set_bit((nr), (addr)) : __clear_bit((nr), (addr)))

fls_long

c 复制代码
/**
 * fls - 查找最后(最高有效)位集
 * @x:要搜索的词
 *
 * 此定义的定义方式与 ffs 相同。
 * 注意 fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32。
 */
static __always_inline int fls(unsigned int x)
{
	return x ? sizeof(x) * 8 - __builtin_clz(x) : 0;
}


static inline unsigned int fls_long(unsigned long l)
{
	if (sizeof(l) == 4)
		return fls(l);
	return fls64(l);
}

BITS_TO_LONGS 位图的字数

  • BITS_TO_LONGS 是一个宏,用于计算给定位数所需的长整型数目。它使用了 __KERNEL_DIV_ROUND_UP 来确保结果向上取整,以便为所有位分配足够的空间。这个宏通常用于处理位图或位数组时,计算所需的存储空间。
  • 例如,如果你有一个位图需要存储 100 位数据,BITS_TO_LONGS(100) 将返回 2,因为在 64 位系统上,一个长整型可以存储 64 位,因此需要两个长整型来存储 100 位数据。
c 复制代码
#define BITS_PER_BYTE		8

#define BITS_PER_TYPE(type)	(sizeof(type) * BITS_PER_BYTE)
#define BITS_TO_LONGS(nr)	__KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
#define BITS_TO_U64(nr)		__KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u64))
#define BITS_TO_U32(nr)		__KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u32))
#define BITS_TO_BYTES(nr)	__KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(char))
相关推荐
1104.北光c°9 分钟前
【从零开始学Redis | 第一篇】Redis常用数据结构与基础
java·开发语言·spring boot·redis·笔记·spring·nosql
Funny_AI_LAB18 分钟前
AI Agent最新重磅综述:迈向高效智能体,记忆、工具学习和规划综述
人工智能·学习·算法·语言模型·agi
Trouvaille ~20 分钟前
【Linux】网络编程基础(三):Socket编程预备知识
linux·运维·服务器·网络·c++·socket·网络字节序
笑锝没心没肺1 小时前
Linux Audit 系统配置介绍
linux·运维·服务器
小义_1 小时前
【RH134知识点问答题】第6章 管理 SELinux 安全性
linux·网络·云原生·rhel
魏波.1 小时前
主流 Linux 发行版有哪些?
linux
REDcker1 小时前
RTSP 直播技术详解
linux·服务器·网络·音视频·实时音视频·直播·rtsp
丁劲犇1 小时前
CentOS 7.6 TCP连接奇慢故障排查:中文注释引发的sysctl配置异常
linux·tcp/ip·centos·速度慢
代码游侠1 小时前
学习笔记——Linux内核与嵌入式开发1
linux·运维·前端·arm开发·单片机·嵌入式硬件·学习
宇钶宇夕2 小时前
CoDeSys入门实战一起学习(二十八):(LD)三台电机顺起逆停程序详解—上升、下降沿使用上
单片机·嵌入式硬件·学习