news 2026/7/11 18:10:49

第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/7/8 21:41:12

储能辅助火电机组二次调频控制策略及容量优化配置研究Simulink实现

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 &#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知,完整Matlab代码获取及仿…

作者头像 李华
网站建设 2026/7/10 13:32:54

I2C与SPI

它们是嵌入式系统和电子设备中两种最重要、最常用的串行通信协议,用于在芯片之间进行短距离、板级的数据交换。 我们可以把它们想象成设备之间“对话”的两种不同方式,各有各的规则和适用场景。 1、I2C(Inter-Integrated Circuit,集成电路总线) I2C是一种多主从、半双工…

作者头像 李华
网站建设 2026/7/10 9:54:51

配电网中的拥塞管理Congestion Management in Distribution Networks

核心定义 配电网中的拥塞管理&#xff0c;是指配电系统运营商&#xff08;DSO&#xff09;采取一系列技术和经济措施&#xff0c;预防、检测和消除配电网中关键设备&#xff08;如线路、电缆、变压器&#xff09;出现的过载或运行越限&#xff0c;以确保电网安全、可靠、高效运…

作者头像 李华
网站建设 2026/7/12 4:07:57

中华人民共和国劳动合同法

官网:中华人民共和国劳动合同法_中国人大网 第一章 总  则 第一条 为了完善劳动合同制度,明确劳动合同双方当事人的权利和义务,保护劳动者的合法权益,构建和发展和谐稳定的劳动关系,制定本法。 第二条 中华人民共和国境内的企业、个体经济组织、民办非企业单位等组…

作者头像 李华
网站建设 2026/7/11 1:19:36

Kotaemon HTTPS 部署教程:SSL证书配置全流程

Kotaemon HTTPS 部署与 SSL 证书配置实战指南 在企业级智能对话系统逐步渗透金融、医疗、政务等高敏感场景的今天&#xff0c;数据传输安全已不再是“可选项”&#xff0c;而是构建可信 AI 服务的基石。Kotaemon 作为专注于生产级 RAG&#xff08;检索增强生成&#xff09;与复…

作者头像 李华
网站建设 2026/7/10 16:15:40

【dz-956】基于单片机的公交车系统

摘要 随着城市公共交通的快速发展&#xff0c;公交车作为市民出行的主要方式之一&#xff0c;其运营效率与服务质量备受关注。传统公交车系统在站点播报、信息展示等方面存在依赖人工操作、信息更新滞后、功能单一等问题&#xff0c;难以满足乘客对精准出行信息的需求&#xf…

作者头像 李华