news 2026/4/3 19:18:13

第5章:并发与竞态条件-16:Bit Operations

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第5章:并发与竞态条件-16:Bit Operations

In continuation of the previous text第5章:并发与竞态条件-15:Atomic Variables, let's GO ahead.

Bit Operations

The atomic_t type is good for performing integer arithmetic. It doesn’t work as well,
however, when you need to manipulate individual bits in an atomic manner. For that
purpose, instead, the kernel offers a set of functions that modify or test single bits
atomically. Because the whole operation happens in a single step, no interrupt (or
other processor) can interfere.

atomic_t类型适用于整数算术运算,但当你需要以原子方式操作单个比特位时,它就不再适用了。针对这类场景,内核提供了一组函数,可原子化地修改或测试单个比特位 —— 由于整个操作在单个步骤中完成,任何中断(或其他处理器)都无法干扰操作过程。

Atomic bit operations are very fast, since they perform the operation using a single
machine instruction without disabling interrupts whenever the underlying platform
can do that. The functions are architecture dependent and are declared in <asm/
bitops.h>. They are guaranteed to be atomic even on SMP computers and are useful
to keep coherence across processors.

原子位操作的执行速度极快:只要底层硬件平台支持,这些操作会通过单条机器指令完成,且无需禁用中断。这类函数与架构强相关,声明在<asm/bitops.h>头文件中;它们能保证在 SMP(对称多处理)系统中仍具备原子性,可有效维持多处理器间的数据一致性。

Unfortunately, data typing in these functions is architecture dependent as well. The
nr argument (describing which bit to manipulate) is usually defined as int but is
unsigned long for a few architectures. The address to be modified is usually a pointer
to unsigned long, but a few architectures use void * instead.

需要注意的是,这些函数的参数类型也与架构相关:

  • nr参数(指定要操作的比特位序号)通常定义为int类型,但部分架构下为unsigned long

  • 待修改数据的地址参数,通常为指向unsigned long的指针,但少数架构中使用void *类型。

The available bit operations are:

// 将addr指向的数据中第nr位设为1 void set_bit(nr, void *addr); /* * 将addr指向的unsigned long类型数据中第nr位清零。 * 其他语义与set_bit一致。 */ void clear_bit(nr, void *addr); // 翻转addr指向数据中第nr位的值(0变1,1变0) void change_bit(nr, void *addr); /* * 该函数是唯一无需原子执行的位操作函数; * 仅返回addr指向数据中第nr位的当前值。 */ test_bit(nr, void *addr); // 原子化设置第nr位,并返回该位操作前的原值 int test_and_set_bit(nr, void *addr); // 原子化清零第nr位,并返回该位操作前的原值 int test_and_clear_bit(nr, void *addr); /* * 原子化翻转第nr位,语义与上述函数一致, * 同时返回该位操作前的原值。 */ int test_and_change_bit(nr, void *addr);

When these functions are used to access and modify a shared flag, you don’t have to
do anything except call them; they perform their operations in an atomic manner.
Using bit operations to manage a lock variable that controls access to a shared vari-
able, on the other hand, is a little more complicated and deserves an example. Most
modern code does not use bit operations in this way, but code like the following still
exists in the kernel.

当使用这些函数访问 / 修改共享标志位时,只需直接调用即可 —— 它们本身已保证操作的原子性。但如果想用位操作实现 “控制共享变量访问的锁”,逻辑会稍复杂,以下是一个示例说明(尽管现代内核代码已很少这样用,但内核中仍存在此类遗留代码)。

A code segment that needs to access a shared data item tries to atomically acquire a
lock using either test_and_set_bit or test_and_clear_bit. The usual implementation is
shown here; it assumes that the lock lives at bit nr of address addr. It also assumes
that the bit is 0 when the lock is free or nonzero when the lock is busy.

若代码段需要访问共享数据,可通过test_and_set_bittest_and_clear_bit原子化获取锁。典型实现逻辑如下:

  • 假设锁对应addr地址的第nr位;

  • 约定:比特位为 0 表示锁空闲,非 0 表示锁被占用。

/* 尝试获取锁 */ while (test_and_set_bit(nr, addr) != 0) wait_for_a_while(); // 锁被占用,等待 /* 执行临界区操作 */ /* 释放锁,并检查状态 */ if (test_and_clear_bit(nr, addr) == 0) something_went_wrong(); // 锁已被释放:出现错误

If you read through the kernel source, you find code that works like this example. It
is, however, far better to use spinlocks in new code; spinlocks are well debugged,

  • they handle issues like interrupts and kernel preemption, and others reading your

code do not have to work to understand what you are doing.

在内核源码中能找到类似上述逻辑的代码,但新代码应优先使用自旋锁而非位操作实现锁机制:自旋锁经过充分调试,能妥善处理中断、内核抢占等问题,且其他开发者阅读代码时,无需额外分析即可理解你的锁逻辑。

补充说明:

1. 原子位操作的核心特性

  • 原子性:操作全程无中断 / 抢占干扰,多 CPU 并发修改同一位时不会出现竞争;

  • 轻量级:无锁的上下文切换 / 自旋开销,仅单条硬件指令(如 x86 的bts/btr指令);

  • 架构兼容性:<asm/bitops.h>会根据 CPU 架构(x86/ARM/RISC-V)封装底层实现,上层代码无需适配。

2. test_bit 非原子性的原因

  • test_bit仅读取位值,不修改数据 —— 即使多 CPU 同时读取同一位,结果也不会出错,因此无需原子化;而set_bit/clear_bit等写操作必须原子化,否则会出现 “读 - 改 - 写” 竞争。

3. 位操作实现锁的缺陷

  • 无抢占 / 中断保护:持有位锁时若发生中断,中断处理程序若也尝试获取该锁,会导致死锁;

  • 无锁排序机制:多把位锁同时获取时,易出现死锁,且无统一的排序规则;

  • 可读性差:需开发者自行约定位的含义,不如自旋锁语义清晰。

4. 原子位操作的正确适用场景

  • 共享标志位:如设备 “忙 / 闲” 状态、中断 “使能 / 禁用” 标记;

  • 位图管理:如内存页分配的位图、设备中断掩码的位操作;

  • 轻量级状态切换:无需完整锁机制的单比特状态修改(如开关类操作)。

5. 现代内核的替代方案

  • 锁机制:优先使用spinlock_t/mutex_t替代位操作实现锁;

  • 标志位管理:仍可使用原子位操作,但仅用于纯状态标记,不用于临界区保护;

  • 多比特操作:若需原子化修改多个比特位,需结合自旋锁 + 普通位操作。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/3 12:33:47

专业的货架电商公司

专业的货架电商公司&#xff1a;柯瑞德货架工厂的卓越之道 在电商蓬勃发展的当下&#xff0c;货架作为仓储物流的重要组成部分&#xff0c;其品质与适用性对企业运营起着关键作用。专业的货架电商公司成为众多企业的首选合作对象&#xff0c;柯瑞德货架工厂便是其中的佼佼者。…

作者头像 李华
网站建设 2026/4/2 23:32:14

抖音碰一下买单是真的吗?支付闭环+拓客引流一站式实现

最近&#xff0c;有消息称&#xff0c;抖音买单将全面升级为抖音碰一下买单。这下&#xff0c;许多原本还秉持观望态度的创业者们可谓是彻底坐不住了&#xff0c;纷纷从各个渠道打听起了入局相关的各项事宜&#xff0c;如抖音碰一下买单服务商怎么申请等。毕竟&#xff0c;从官…

作者头像 李华
网站建设 2026/4/3 18:23:30

低代码搭桥,BI 赋能:让每一份数据都生钱

在数字化转型进入深水区的今天&#xff0c;几乎所有企业都面临着一个共性困境&#xff1a;数据躺在系统里"沉睡"&#xff0c;生产、库存、销售等环节的信息割裂成"孤岛"&#xff0c;明明握着价值金矿&#xff0c;却苦于无法高效开采。传统IT开发周期长、成…

作者头像 李华
网站建设 2026/4/3 5:26:50

嵌入式模组的温度传感器数据传输方法

1、硬件层信号采集 (1)传感器类型: 数字传感器:直接通过I2C、SPI、1-Wire等协议输出数字信号。 (2)硬件连接: 传感器通过电路连接到微控制器的GPIO、ADC引脚或通信接口(I2C/SPI总线)。 2、底层驱动与数据传输 (1)数字传感器处理流程 通信协议驱动:I2C/SPI:微…

作者头像 李华
网站建设 2026/4/3 3:08:14

华三Telnet/SSH配置指南

文档版本&#xff1a;V1.0 一、Telnet与SSH协议介绍 1.1 Telnet协议 Telnet&#xff08;Telecommunication Network&#xff09;是基于TCP/IP协议的远程登录协议&#xff0c;默认使用23号端口。该协议允许管理员通过网络远程登录至网络设备&#xff08;如交换机、路由器&…

作者头像 李华