imx6ull-驱动开发篇16——信号量与互斥体

目录

前言

信号量

概念与特性

信号量 API 函数

互斥体

概念与特性

互斥体 API 函数


前言

Linux 内核提供的几种并发和竞争的处理方法,我们学习了:

驱动开发篇14——原子操作

驱动开发篇15——linux自旋锁

本讲我们就继续学习:信号量和互斥体。

信号量

概念与特性

Linux 内核提供了信号量机制,信号量常常用于控制对共享资源的访问。

信号量是一种​​睡眠锁​​机制,通过计数器控制对共享资源的访问:

  • ​​计数器值​​:表示可用资源数量
  • ​​P操作​​:申请资源(值减1,若为0则阻塞)
  • ​​V操作​​:释放资源(值加1,唤醒等待者)

信号量常见的有4种类型:

这几个信号量的主要区别如下:

总结一下信号量的特点:

  • 信号量可以使等待资源线程进入休眠状态,因此适用于那些占用资源比较久的场合。
  • 信号量不能用于中断中,因为信号量会引起休眠,中断不能休眠。
  • 如果共享资源的持有时间比较短,那就不适合使用信号量了,因为频繁的休眠、切换线程引起的开销要远大于信号量带来的那点优势。

信号量 API 函数

Linux 内核使用 semaphore 结构体表示信号量,结构体内容如下:

struct semaphore {raw_spinlock_t lock;      // 保护信号量结构的自旋锁unsigned int count;       // 可用资源计数器struct list_head wait_list; // 等待进程链表
};

有关信号量的 API 函数如表:

示例代码如下:

#include <linux/module.h>
#include <linux/semaphore.h>
#include <linux/sched.h>// 定义并初始化信号量(方法1)
static DEFINE_SEMAPHORE(my_sem);// 动态信号量(方法2)
static struct semaphore dynamic_sem;static int __init semaphore_demo_init(void)
{printk(KERN_INFO "Semaphore Demo Start\n");// 初始化动态信号量(初始值设为2)sema_init(&dynamic_sem, 2);// 1. 基本获取/释放down(&my_sem);printk("Process %d entered critical section\n", current->pid);up(&my_sem);// 2. 非阻塞尝试if (down_trylock(&dynamic_sem) == 0) {printk("Got semaphore without waiting\n");up(&dynamic_sem);} else {printk("Semaphore busy, continue other work\n");}// 3. 可中断等待if (down_interruptible(&dynamic_sem)) {printk("Interrupted by signal\n");return -ERESTARTSYS;}/* 临界区操作(可安全休眠) */msleep(100);up(&dynamic_sem);return 0;
}static void __exit semaphore_demo_exit(void)
{printk(KERN_INFO "Semaphore Demo End\n");
}module_init(semaphore_demo_init);
module_exit(semaphore_demo_exit);
MODULE_LICENSE("GPL");

互斥体

概念与特性

将信号量的值设置为 1,就可以通过信号量实现互斥,但是 Linux 提供了一个比信号量更专业的机制来进行互斥,它就是互斥体—mutex。

互斥体(Mutual Exclusion)是一种​​睡眠锁​​机制,用于保护临界区资源,具有以下特性:

  • ​​独占访问​​:同一时间仅允许一个线程持有锁
  • ​​睡眠等待​​:获取锁失败时让出CPU(非忙等待)
  • ​​进程上下文​​:只能在可调度上下文中使用

和自旋锁、信号相比,互斥体的优势如下:

Linux (5.15+)内核使用 mutex 结构体表示互斥体,定义如下:

struct mutex {atomic_long_t owner;          // 持有者标识 + 状态标志spinlock_t wait_lock;        // 保护等待队列的自旋锁struct list_head wait_list;   // 等待线程链表
#ifdef CONFIG_DEBUG_MUTEXESconst char *name;             // 调试用名称void *magic;                  // 调试用魔数
#endif
};

在使用 mutex 之前要先定义一个 mutex 变量。

在使用 mutex 的时候要注意如下几点:

  • mutex 可以导致休眠,因此不能在中断中使用 mutex,中断中只能使用自旋锁。
  • 和信号量一样, mutex 保护的临界区可以调用引起阻塞的 API 函数。
  • 因为一次只有一个线程可以持有 mutex,因此,必须由 mutex 的持有者释放 mutex。并且 mutex 不能递归上锁和解锁。

互斥体 API 函数

有关互斥体的 API 函数如表:

示例代码如下:

#include <linux/module.h>
#include <linux/mutex.h>static DEFINE_MUTEX(global_mutex);  // 静态定义并初始化全局互斥体
static struct mutex dynamic_mutex;  // 动态互斥体
static int shared_data = 0;         // 共享数据static int __init mutex_demo_init(void)
{printk(KERN_INFO "Mutex Demo Start\n");// 1. 初始化动态互斥体mutex_init(&dynamic_mutex);// 2. 检查锁状态printk("Global mutex is %slocked\n", mutex_is_locked(&global_mutex) ? "" : "not ");// 3. 基本加锁/解锁mutex_lock(&global_mutex);shared_data = 100;mutex_unlock(&global_mutex);// 4. 尝试获取锁(非阻塞)if (mutex_trylock(&dynamic_mutex)) {printk("Got dynamic mutex immediately\n");mutex_unlock(&dynamic_mutex);} else {printk("Dynamic mutex is busy\n");}// 5. 可中断锁(推荐用法)if (mutex_lock_interruptible(&global_mutex)) {printk("Interrupted by signal while waiting\n");return -ERESTARTSYS;}/* 临界区操作(可安全休眠) */shared_data += 50;msleep(10);  // 模拟耗时操作mutex_unlock(&global_mutex);return 0;
}static void __exit mutex_demo_exit(void)
{// 确保所有锁已释放if (!mutex_is_locked(&dynamic_mutex)) {mutex_lock(&dynamic_mutex);shared_data = 0;mutex_unlock(&dynamic_mutex);}printk(KERN_INFO "Final shared_data: %d\n", shared_data);printk(KERN_INFO "Mutex Demo End\n");
}module_init(mutex_demo_init);
module_exit(mutex_demo_exit);
MODULE_LICENSE("GPL");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/918276.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/918276.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Bug 记录:SecureRandom.getInstanceStrong()导致验证码获取阻塞

问题描述&#xff1a; 在发送验证码到邮件中&#xff0c;接口调用时卡在生成验证码阶段&#xff0c;导致验证码功能完全不可用&#xff1b; 经排查开发环境一切正常&#xff0c;测试环境会重现此问题&#xff1b;问题分析&#xff1a; 现象&#xff1a; 代码卡在 SecureRandom.…

商派小程序商城(小程序/官网/APP···)的范式跃迁与增长再想象

2025年&#xff0c;品牌官方商城应该如何定义&#xff1f;—— 还是一套“电商货架”&#xff1f;在商派看来&#xff0c;现如今“品牌官方商城”则需要重新定义&#xff0c;结合不同品牌企业的业务发展需求&#xff0c;也就有着更多丰富的定义和组合想象——如&#xff0c;商城…

基于串口实现可扩展的硬件函数 RPC 框架(附完整 Verilog 源码)

本文介绍如何使用简单的串口协议搭建一个支持寄存器读写与硬件函数调用的通用交互框架&#xff0c;适用于 FPGA 调试、嵌入式接口、中小型控制系统等场合。 特性&#xff1a; 轻量协议、30 个32位寄存器、函数调用、状态反馈&#xff0c;源码清晰易扩展。&#x1f4a1; 背景与目…

jenkins-飞书通知机制

一. 目标&#xff1a; 触发构建和结束后&#xff0c;自动触发到飞书工作群&#xff0c;发布同学只需要关注消息即可&#xff0c;而无需人工盯梢。 二. 实现方式&#xff1a; 1. 机器人配置&#xff1a; 创建一个群&#xff0c; 配置机器人&#xff1a; 保管好下面的webhoo…

GoLand 项目从 0 到 1:第五天 —— 角色权限中间件实现与事务控制

第五天核心任务:权限校验链路闭环 第五天的开发聚焦于权限控制的核心实现,完成了角色权限中间件的开发,实现了接口级别的权限校验,并基于事务控制确保用户权限操作的数据一致性。通过这部分工作,系统的权限管理从设计阶段正式进入可运行阶段,为后续业务模块的安全接入提…

【工具变量】地级市固定资产投资数据(2000-2023年)

数据简介&#xff1a;地级市固定资产投资是衡量地方经济发展活力与动能的重要指标&#xff0c;其规模、结构及增速不仅反映区域产业布局和政策导向&#xff0c;也直接影响基础设施完善、产业升级和民生改善。清晰展现长期经济发展脉络&#xff0c;助力捕捉经济增长与波动规律。…

Kotlin初体验

前言&#xff1a; 在当今的软件开发领域&#xff0c;随着技术的不断发展&#xff0c;开发者总是在寻找更高效、更简洁的编程语言来提升开发效率并减少代码中的潜在问题。而 Kotlin&#xff0c;作为一门现代的编程语言&#xff0c;逐渐赢得了越来越多开发者的青睐&#xff0c;尤…

五十五、【Linux系统nginx服务】nginx安装、用户认证、https实现

一、Nginx 核心功能全景图 #mermaid-svg-j5M1WUQFrtyrWjAD {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-j5M1WUQFrtyrWjAD .error-icon{fill:#552222;}#mermaid-svg-j5M1WUQFrtyrWjAD .error-text{fill:#552222;s…

AtCoder Beginner Contest 418

文章目录A Im a teapotB Youre a teapotC FlushD XNOR OperationE TrapeziumF Were teapotsG Binary OperationAtCoder Beginner Contest 418A I’m a teapot Takahashi is a teapot. Since he is a teapot, he will gladly accept tea, but will refuse any other liquid. Det…

多级缓存详解

多级缓存 传统缓存&#xff1a; 传统缓存策略一般是请求到达Tomcat后&#xff0c;先查询Redis&#xff0c;如果未命中则查询数据库。 这种模式下请求一定要经过Tomcat处理&#xff0c;Tomcat的性能就成为了整个系统的瓶颈&#xff1b;并且Redis的缓存也有过期时间&#xff0c;一…

接口自动化-JSON Schema

目录 1.介绍 2.安装 3.使用 3.1type关键字 3.2最大值最小值 3.2.1minimum 、 maximum 3.2.2 exclusiveMinimum 、exclusiveMaximum 3.3字符串特殊校验 3.4数据约束 3.5对象约束 3.6必须属性 3.7依赖关系 4.总结 1.介绍 JSON Schema 是一个用来定义和校验 JSON 的…

前端技术架构设计文档(Vue2+Antd+Sass)

前端技术架构设计文档&#xff08;Vue2AntdSass&#xff09; 文档信息项目名称前端系统&#xff08;基于 Vue2 技术栈&#xff09;技术栈核心Vue2 Ant Design Vue Sass版本号V1.0.0技术栈核心Vue2 Ant Design Vue Sass编制日期2025-08-071. 技术栈选型 1.1 核心技术框架类别…

【设计模式】抽象工厂模式 (工具(Kit)模式)

抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;详解一、抽象工厂模式简介 抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09; 是一种 创建型设计模式&#xff08;对象创建型模式&#xff09;&#xff0c;它提供了一种创建一系列相关或相互依赖对象…

Android初学者系统开发学习路线参考

Android初学者系统开发学习路线参考 文章目录Android初学者系统开发学习路线参考一、前言二、Android初学的学习计划第一阶段&#xff08;一个月&#xff09;UI相关学习&#xff1a;开发环境与 UI 基础&#xff0c;第一周&#xff1a;UI 控件与布局进阶&#xff0c;第二周&…

扩散LLM推理新范式:打破生成长度限制,实现动态自适应调节

随着 Gemini-Diffusion&#xff0c;Seed-Diffusion 等扩散大语言模型&#xff08;DLLM&#xff09;的发布&#xff0c;这一领域成为了工业界和学术界的热门方向。但是&#xff0c;当前 DLLM 存在着在推理时必须采用预设固定长度的限制&#xff0c;对于不同任务都需要专门调整才…

【ee类保研面试】其他类---计算机网络

25保研er&#xff0c;希望将自己的面试复习分享出来&#xff0c;供大家参考 part0—英语类 part1—通信类 part2—信号类 part3—高数类 part100—self项目准备 文章目录计算机网络知识点大全**计算机网络知识点总结**一、五层协议模型二、OSI七层模型补充三、TCP 与 UDP 及区别…

Python-机器学习(一)——特征工程

目录 特征工程 一、特征提取 1、字典特征提取 2、文本特征提取 2.1 英文文本提取 2.2 中文文本提取 3、TF-IDF文本特征词的重要程度特征提取 二、无量纲化-预处理 1 MinMaxScaler 归一化 2 normalize归一化 3 StandardScaler 标准化 三、特征降维 1、特征选择 1.…

谈谈SQL计算存储引擎中的索引和计算

背景 最近在这家公司做了一些事情&#xff0c;做的事情和以往的工作不太一样&#xff0c;不一样的点呢就是 之前我主要的工作是关注计算这方面&#xff0c;因为数据量大&#xff0c;研究的是怎么加速查询&#xff0c;怎么研究规则去优化&#xff0c;怎么去解规则的bug等等。因为…

vscode.window.activeTextEditor 获取不到 png 图片路径问题

vscode 的 extensions 插件开发时用 vscode.window.activeTextEditor?.document.uri 获取不到编辑器打开的图片路径&#xff0c;文档路径可以获取到。个人猜测因为图片不能编辑&#xff0c;所以没有 activeTextEditor 属性吧。解决办法&#xff1a;巧用右键获取路径和相对的路…

Java 大视界 -- Java 大数据在智能医疗手术机器人操作数据记录与性能评估中的应用(390)

Java 大视界 -- Java 大数据在智能医疗手术机器人操作数据记录与性能评估中的应用&#xff08;390&#xff09;引言&#xff1a;正文&#xff1a;一、传统手术机器人的 “黑箱困境”&#xff1a;记不全、算不清、追不到1.1 设备与临床的 “断层”1.1.1 数据记录 “太粗放”1.1.…