Linux内核之互斥锁mutex_init和自旋锁spin_lock区别及用法实例(四十六)

本文主要是介绍Linux内核之互斥锁mutex_init和自旋锁spin_lock区别及用法实例(四十六),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀
优质专栏:多媒体系统工程师系列原创干货持续更新中……】🚀
优质视频课程:AAOS车载系统+AOSP14系统攻城狮入门实战课原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

🍉🍉🍉文章目录🍉🍉🍉

    • 🌻1.前言
    • 🌻2.介绍
      • 🐓2.1 互斥锁mutex_init介绍
      • 🐓2.2 自旋锁spin_lock介绍
      • 🐓2.3 用法区别
      • 🐓2.4性质和适用场景:
      • 🐓2.5 mutex_lock、 mutex_unlock 、spin_lock、spin_unlock用法
    • 🌻3.代码实例
      • 🐓3.1 互斥锁mutex_init示例
      • 🐓3.2 自旋锁spin_lock示例
      • 🐓3.3 互斥锁和自旋锁组合使用

🌻1.前言

本篇目的:Linux内核之互斥锁mutex_init和自旋锁spin_lock区别及用法实例

🌻2.介绍

  • 在Linux内核中,mutex_initspin_lock是两种常用的同步机制,用于在多线程或多处理器环境中保护共享资源,防止并发访问造成的数据不一致问题。

🐓2.1 互斥锁mutex_init介绍

  • mutex_init用于初始化一个互斥锁(mutex),它是一种睡眠锁。
  • 当一个线程尝试获取一个已经被其他线程持有的互斥锁时,该线程会被阻塞,进入睡眠状态,直到互斥锁被释放。
  • 互斥锁适用于那些可能造成较长时间阻塞的场景,因为线程睡眠状态不会消耗CPU资源。
  • 用法示例:
#include <linux/mutex.h>
struct mutex my_mutex;
void my_init_function(void) {mutex_init(&my_mutex); // 初始化互斥锁
}
void my_function(void) {mutex_lock(&my_mutex); // 获取互斥锁// 临界区代码mutex_unlock(&my_mutex); // 释放互斥锁
}

🐓2.2 自旋锁spin_lock介绍

  • spin_lock是一种自旋锁,它的工作原理是在一个循环中不断地检查锁是否可用。
  • 如果锁被占用,线程会持续检查,而不是进入睡眠状态。
  • 这意味着自旋锁适用于那些预期等待时间非常短的场景,因为自旋状态会占用CPU资源。
    用法示例:
#include <linux/spinlock.h>
DEFINE_SPIN_LOCK(my_spinlock);
void my_function(void) {unsigned long flags;spin_lock_irqsave(&my_spinlock, flags); // 获取自旋锁,并保存中断状态// 临界区代码spin_unlock_irqrestore(&my_spinlock, flags); // 释放自旋锁,并恢复中断状态
}

🐓2.3 用法区别

  1. 阻塞与自旋mutex会导致线程睡眠,不会消耗CPU资源,而spin_lock会持续占用CPU资源,直到锁被释放。
  2. 使用场景mutex适用于可能造成长时间阻塞的场景,如等待I/O操作完成。spin_lock适用于预期等待时间非常短的场景,如简单的数据结构操作。
  3. 性能影响mutex在阻塞和唤醒线程时会有较大的性能开销,而spin_lock在等待锁释放时只会占用CPU资源,没有线程切换的开销。
  4. 中断处理:在Linux内核中,自旋锁常常与中断处理相关,因为中断处理函数不能睡眠。使用spin_lock_irqsave可以在获取锁的同时关闭中断,确保临界区的原子性。
  • 选择mutex还是spin_lock取决于临界区的性质和预期的等待时间。对于可能长时间阻塞的操作,使用mutex更合适;而对于非常快速的操作,使用spin_lock可能更高效。

🐓2.4性质和适用场景:

  • mutex_init:适用于需要在内核中进行睡眠等待的同步操作,因为互斥锁(mutex)可以导致任务进入睡眠状态并被放置在等待队列中。
  • spin_lock:适用于需要在内核中进行自旋等待的同步操作,因为自旋锁(spinlock)会导致任务在一个循环中不断尝试获取锁,直到成功,而不会引起任务的睡眠。

🐓2.5 mutex_lock、 mutex_unlock 、spin_lock、spin_unlock用法

  • mutex_init:通过 mutex_init 函数初始化互斥锁,然后可以使用 mutex_lock 和 mutex_unlock 函数来获取和释放锁。
  • spin_lock:通过 spin_lock 函数获取自旋锁,通过 spin_unlock 函数释放自旋锁。

🌻3.代码实例

🐓3.1 互斥锁mutex_init示例

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mutex.h>static DEFINE_MUTEX(my_mutex); // 定义互斥锁static int __init my_init(void)
{printk(KERN_INFO "Initializing my driver\n");mutex_init(&my_mutex); // 初始化互斥锁// 其他初始化代码...return 0;
}static void __exit my_exit(void)
{printk(KERN_INFO "Exiting my driver\n");mutex_destroy(&my_mutex); // 销毁互斥锁// 其他清理代码...
}module_init(my_init);
module_exit(my_exit);

🐓3.2 自旋锁spin_lock示例

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/spinlock.h>static DEFINE_SPINLOCK(my_spinlock); // 定义自旋锁static int __init my_init(void)
{printk(KERN_INFO "Initializing my driver\n");// 其他初始化代码...return 0;
}static void __exit my_exit(void)
{printk(KERN_INFO "Exiting my driver\n");
}module_init(my_init);
module_exit(my_exit);

🐓3.3 互斥锁和自旋锁组合使用

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>static DEFINE_MUTEX(my_mutex); // 定义互斥锁
static DEFINE_SPINLOCK(my_spinlock); // 定义自旋锁static int __init my_init(void)
{printk(KERN_INFO "Initializing my driver\n");mutex_init(&my_mutex); // 初始化互斥锁return 0;
}static void __exit my_exit(void)
{printk(KERN_INFO "Exiting my driver\n");mutex_destroy(&my_mutex); // 销毁互斥锁
}module_init(my_init);
module_exit(my_exit);

这篇关于Linux内核之互斥锁mutex_init和自旋锁spin_lock区别及用法实例(四十六)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/899516

相关文章

python版本切换工具pyenv的安装及用法

《python版本切换工具pyenv的安装及用法》Pyenv是管理Python版本的最佳工具之一,特别适合开发者和需要切换多个Python版本的用户,:本文主要介绍python版本切换工具pyen... 目录Pyenv 是什么?安装 Pyenv(MACOS)使用 Homebrew:配置 shell(zsh

Java中的CompletableFuture核心用法和常见场景

《Java中的CompletableFuture核心用法和常见场景》CompletableFuture是Java8引入的强大的异步编程工具,支持链式异步编程、组合、异常处理和回调,介绍其核心用法,通过... 目录1、引言2. 基本概念3. 创建 CompletableFuture3.1. 手动创建3.2.

MySQL 筛选条件放 ON后 vs 放 WHERE 后的区别解析

《MySQL筛选条件放ON后vs放WHERE后的区别解析》文章解释了在MySQL中,将筛选条件放在ON和WHERE中的区别,文章通过几个场景说明了ON和WHERE的区别,并总结了ON用于关... 今天我们来讲讲数据库筛选条件放 ON 后和放 WHERE 后的区别。ON 决定如何 "连接" 表,WHERE

Mybatis的mapper文件中#和$的区别示例解析

《Mybatis的mapper文件中#和$的区别示例解析》MyBatis的mapper文件中,#{}和${}是两种参数占位符,核心差异在于参数解析方式、SQL注入风险、适用场景,以下从底层原理、使用场... 目录MyBATis 中 mapper 文件里 #{} 与 ${} 的核心区别一、核心区别对比表二、底

Nginx服务器部署详细代码实例

《Nginx服务器部署详细代码实例》Nginx是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务,:本文主要介绍Nginx服务器部署的相关资料,文中通过代码... 目录Nginx 服务器SSL/TLS 配置动态脚本反向代理总结Nginx 服务器Nginx是一个‌高性

Linux内核定时器使用及说明

《Linux内核定时器使用及说明》文章详细介绍了Linux内核定时器的特性、核心数据结构、时间相关转换函数以及操作API,通过示例展示了如何编写和使用定时器,包括按键消抖的应用... 目录1.linux内核定时器特征2.Linux内核定时器核心数据结构3.Linux内核时间相关转换函数4.Linux内核定时

MySQL中between and的基本用法、范围查询示例详解

《MySQL中betweenand的基本用法、范围查询示例详解》BETWEENAND操作符在MySQL中用于选择在两个值之间的数据,包括边界值,它支持数值和日期类型,示例展示了如何使用BETWEEN... 目录一、between and语法二、使用示例2.1、betwphpeen and数值查询2.2、be

Linux镜像文件制作方式

《Linux镜像文件制作方式》本文介绍了Linux镜像文件制作的过程,包括确定磁盘空间布局、制作空白镜像文件、分区与格式化、复制引导分区和其他分区... 目录1.确定磁盘空间布局2.制作空白镜像文件3.分区与格式化1) 分区2) 格式化4.复制引导分区5.复制其它分区1) 挂载2) 复制bootfs分区3)

Spring Boot Interceptor的原理、配置、顺序控制及与Filter的关键区别对比分析

《SpringBootInterceptor的原理、配置、顺序控制及与Filter的关键区别对比分析》本文主要介绍了SpringBoot中的拦截器(Interceptor)及其与过滤器(Filt... 目录前言一、核心功能二、拦截器的实现2.1 定义自定义拦截器2.2 注册拦截器三、多拦截器的执行顺序四、过

Go异常处理、泛型和文件操作实例代码

《Go异常处理、泛型和文件操作实例代码》Go语言的异常处理机制与传统的面向对象语言(如Java、C#)所使用的try-catch结构有所不同,它采用了自己独特的设计理念和方法,:本文主要介绍Go异... 目录一:异常处理常见的异常处理向上抛中断程序恢复程序二:泛型泛型函数泛型结构体泛型切片泛型 map三:文