Linux驱动开发笔记(十二)并发与竞争

文章目录

  • 前言
  • 一、并发与竞争的引入
    • 1.1 并发
    • 1.2 竞争
    • 1.3 解决方法
  • 二、原子操作
    • 2.1 概念
    • 2.2 使用方法
  • 三、自旋锁
    • 3.1 概念
    • 3.2 使用方法
    • 3.3 自旋锁死锁
  • 四、信号量
    • 4.1 概念
    • 4.2 使用方法
  • 五、互斥锁
    • 5.1 概念
    • 5.2 使用方法


前言

  Linux的子系统我们已经大致学习完了,笔者最近相到似乎一直没有好好学习一下并发和竞争这一部分内容(在网络编程中曾经简单提到过Linux应用开发笔记(五)网络编程(二)多线程编程)。


一、并发与竞争的引入

1.1 并发

  以下图为例,我们的CPU在同时处理多个任务的时候也可能采取类似“分时复用”的手法,即在不同的工作时间块内切换执行的任务,使得在实际效果上好像认为是这些任务是在同时运行的,这种操作方法我们称为并发。
在这里插入图片描述
  通常情况下,通过并发执行多个任务,可以充分利用多核处理器,提高程序的执行效率减少资源的闲置时间

1.2 竞争

  在并发的过程中,经常产生不同的程序共享一个资源的情况,这种行为既可以减少资源但也会产生抢占的问题,这种情况我们称之为竞争。

1.3 解决方法

  其实竞争的产生可以理解为是多个线程或进程需要访问和修改相同的资源(如全局变量、文件、数据库等),且没有适当的同步机制。那么如何解决这个问题呢?在Linux中提供了原子操作、自旋锁、互斥锁、信号量等同步机制。
在这里插入图片描述

二、原子操作

2.1 概念

  原子操作是一种不可分割的操作,确保在多线程或多进程环境下,该操作可以在没有中断的情况下完成。原子操作在执行过程中不会被其他线程或进程打断,确保了数据的一致性和正确性。
  在并发编程中,多个线程或进程可能会同时访问和修改共享数据。普通的读写操作可能会引发竞争条件(Race Condition),导致数据不一致。原子操作提供了一种机制,确保共享数据的修改是安全的,即使在高度并发的环境中。
  在Linux内核中使用 atomic_t和atomic64_t结构体分别来完成32位系统和64位系统的整形数据原子操作,两个结构体定义在“内核源码/include/linux/types.h”文件中,具体定义如下:

 typedef struct {int counter;} atomic_t;#ifdef CONFIG_64BITtypedef struct {long counter;
} atomic64_t;#endif

在这里插入图片描述
注:这是64位系统的函数集,如果是32位只需要将函数名中的64删去即可。

2.2 使用方法

  我们可以使用以下代码定义一个64位系统的原子整型变量,其实细心的读者可能会发现我们在之前中断实验的时候已经使用过这种方式了,当时为了防止持续进入中断函数导致计数出错。

static atomic64_t v = ATOMIC_INIT(1);//初始化原子类型变量v,并设置为1

  之后我们便可以根据对原子量进行赋值来定义不同的状态,从而告诉cpu这个资源已经占用,例如:

//本次的所有实验均为拒绝重复打开驱动 
static int open(struct inode *inode,struct file *file)
{//判断是否是重复进入if(atomic64_read(&v) != 1){return -EBUSY;printk("\t This process has opened! \n");}//第一次进入,将v的值设置为0atomic64_set(&v,0);return 0;
}static int release_test(struct inode *inode,struct file *file)
{atomic64_set(&v,1);//将原子类型变量v的值赋1return 0;
}

三、自旋锁

3.1 概念

  自旋锁(spin lock)是一种非阻塞锁,也就是说,如果某线程需要获取锁,但该锁已经被其他线程占用时,该线程不会被挂起,而是在不断的消耗CPU的时间,不停的试图获取锁。如果在自旋完成后前面锁定同步资源的线程已经释放了锁,那么该线程便不必阻塞,并且直接获取同步资源,从而避免切换线程的开销。

//表示自旋锁
typedef struct spinlock {union {struct raw_spinlock rlock;#ifdef CONFIG_DEBUG_LOCK_ALLOC
# define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_map))struct {u8 __padding[LOCK_PADSIZE];struct lockdep_map dep_map;};
#endif};
} spinlock_t;

在这里插入图片描述
  上图是自旋锁的相关API,一般来说我们使用这些函数就足够了,下图是中断的自旋锁API,这里仅进行补充。
在这里插入图片描述
注:为了保险起见,我们通常选择使用spin_lock_irqsave进行自旋锁获取。

3.2 使用方法

代码如下(示例):

//定义spinlock_t类型的自旋锁变量spinlock_test
static spinlock_t spinlock_test;//定义全局变量flag,flag等于1表示设备没有被打开,等于0则证明设备已经被打开了
static int flag = 1;static int open(struct inode *inode,struct file *file)
{//自旋锁加锁spin_lock(&spinlock_test);if(flag != 1){spin_unlock(&spinlock_test);//自旋锁解锁return -EBUSY;}flag = 0;//自旋锁解锁spin_unlock(&spinlock_test);return 0;
}static int release_test(struct inode *inode,struct file *file)
{spin_lock(&spinlock_test);//自旋锁加锁flag = 1;spin_unlock(&spinlock_test);//自旋锁解锁return 0;
}static int __init init(void)
{//初始化自旋锁spin_lock_init(&spinlock_test);...
}

3.3 自旋锁死锁

  自旋锁死锁是指两个或多个事物在同一资源上相互占用,并请求锁定对方的资源,从而导致恶性循环的现象。当多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进,这种情况就是死锁。自旋锁死锁发生存在两种情况:
(1)拥有自旋锁的进程A在内核态阻塞了,内核调度B进程,碰巧B进程也要获得自旋锁,此时B只能自旋转。而此时抢占已经关闭(在单核条件下)不会调度A进程了,B永远自旋,产生死锁。
  相应的解决办法是,在自旋锁的使用过程中要尽可能短的时间内拥有自旋锁,而且不能在临界区中调用导致线程休眠的函数。
(2)进程A拥有自旋锁,中断到来,CPU执行中断函数,中断处理函数,中断处理函数需要获得自旋锁,访问共享资源,此时无法获得锁,只能自旋,从而产生死锁。
  对于中断引发的死锁,最好的解决方法就是在获取锁之前关闭本地中断,由于Linux内核运行是非常复杂的,很难确定某个时刻的中断状态,因此建议使用 spin_lock_irqsave/spin_unlock_irqrestore,因为这一组函数会保存中断状态,在释放锁的时候会恢复中断状态。

四、信号量

4.1 概念

  信号量是操作系统中最典型的用于同步和互斥的手段,本质上是一个全局变量,信号量的值表示控制访问资源的线程数,可以根据实际情况来自行设置,如果在初始化的时候将信号量量值设置为大于1,那么这个信号量就是计数型信号量,允许多个线程同时访问共享资源;如果将信号量量值设置为1,那么这个信号量就是二值信号量,同一时间内只允许一个线程访问共享资源;信号量的值不能小于0,当信号量的值为0时,想访问共享资源的线程必须等待,直到信号量大于0时,等待的线程才可以访问。

//表示一个信号量struct semaphore {raw_spinlock_t      lock;unsigned int        count;struct list_head    wait_list;};

在这里插入图片描述
  当访问共享资源时,信号量执行“减1”操作,访问完成后再执行“加1”操作,这里的down函数可以理解为减1操作,up函数可以理解为加1操作。

4.2 使用方法

代码如下(示例):

//定义一个semaphore类型的结构体变量semaphore_test
struct semaphore semaphore_test;static int open(struct inode *inode,struct file *file)
{//信号量数量减1down(&semaphore_test);return 0;
}static int release_test(struct inode *inode,struct file *file)
{//信号量数量加1up(&semaphore_test);return 0;
}static int __init init(void)
{//初始化信号量结构体semaphore_test,并设置信号量的数量为1sema_init(&semaphore_test,1);...
}

五、互斥锁

5.1 概念

  互斥锁为资源引入一个状态:锁定或者非锁定。某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁和信号量功能相同,但具体的实现方式是不同的,此外使用互斥锁效率更高、更简洁,所以如果使用到的信号量“量值”为 1,一般将其修改为使用互斥锁实现。

struct mutex {atomic_long_t       owner;spinlock_t      wait_lock;#ifdef CONFIG_MUTEX_SPIN_ON_OWNERstruct optimistic_spin_queue osq; /* Spinner MCS lock */#endifstruct list_head    wait_list;#ifdef CONFIG_DEBUG_MUTEXESvoid            *magic;#endif#ifdef CONFIG_DEBUG_LOCK_ALLOCstruct lockdep_map  dep_map;#endif};

在这里插入图片描述

5.2 使用方法

代码如下(示例):

//定义mutex类型的互斥锁结构体变量mutex_test
struct mutex mutex_test;static int open(struct inode *inode,struct file *file)
{//互斥锁加锁mutex_lock(&mutex_test);return 0;
}static int release_test(struct inode *inode,struct file *file)
{//互斥锁解锁mutex_unlock(&mutex_test);return 0;
}static int __init init(void)
{//对互斥体进行初始化mutex_init(&mutex_test);...
}

免责声明:本内容部分参考野火科技及其他相关公开资料,若有侵权或者勘误请联系作者。

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

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

相关文章

项目测试排期的正确方法是什么?

测试排期是项目排期里面的一部分,所以了解项目排期对整体产品的全貌会有一个宏观的认知,甘特图能很好的体现项目排期,里面包含了参与角色和每个角色对应的排期。项目参与者和项目责任人都可以清晰的看到项目当前进展和项目耗时等。 甘特图可…

c++习题03-分卡片

目录 一,题目 二,思路 三,代码 一,题目 二,思路 在做题的时候一定要认真审题,抓住关键的点和条件,才能够更高效的做对题目。 上面的题目有以下关键点(关键条件&#xff0…

Transformer2--Multi-head self-attention

目录 一、背景二、多头自注意力机制的原理2.1 自注意力机制2.2 多头自注意力机制2.3 Positional Encoding(位置编码)2.4 self-attention for image 三、Self-attention v.s CNN四、Self-attention v.s RNN参考资料 一、背景 为什么是multi-head self at…

CocosCreator构建IOS的wwise教程

CocosCreator构建IOS教程 添加wwise教程: 1.添加include 2.添加SoundEngine 3.添加Profile-iphoneos下面lib下面的.a 4.导入js调用C++的文件 5.导入这些文件 6.初始化ios绝对路径和TTS语音合成对象 6.获得根目录绝对路径,加载pck需要找到绝对路径。怎么找绝对路径? #impor…

2024年危化品安全员生产单位(生产管理人员)考试精选题库

31.《危险化学品安全管理条例》所称重大危险源,是指生产、储存、使用或者搬运危险化学品,且危险化学品的数量等于或者超过()的单元(包括场所和设施)。 A.标准 B.一定量 C.临界量 答案:C 32.《危险化学品生产企业安全生产许可证实施办法》…

C语言分支和循环(上)

C语言分支和循环(上) 1. if语句1.1 if1.2 else1.3 分支中包含多条语句1.4 嵌套if1.5 悬空else问题 2. 关系操作符3. 条件操作符4. 逻辑操作符:&&,||,!4.1 逻辑取反运算符4.2 与运算符4.3 或运算符4.4 练习:闰年…

加密与安全_Java 加密体系 (JCA) 和 常用的开源密码库

文章目录 Java Cryptography Architecture (JCA)开源国密库国密算法对称加密(DES/AES⇒SM4)非对称加密(RSA/ECC⇒SM2)散列(摘要/哈希)算法(MD5/SHA⇒SM3) 在线生成公钥私钥对,RSA公私钥生成参考…

黑苹果系统(MacOS)配置清单

手里的MacBookPro已经快沦为电子垃圾了,平时用MacOS比较多,Window用的比较少,而苹果电脑的价格不管是MacBookPro还是MacMini丐版的便宜但是面对现在Window动不动就64g内存的情况就显得微不足道了,高配的价格直接把我劝退&#xff…

招聘,短信与您:招聘人员完整指南

招聘人员面临的最大挑战之一就是沟通和联系候选人。为何?我们可以从以下原因开始:候选人通常被太多的招聘人员包围,试图联系他们,这使得你很难吸引他们的注意。在招聘过程的不同阶段,根据不同的工作量,让申请人保持最…

【ACM_2023】3D Gaussian Splatting for Real-Time Radiance Field Rendering

【ACM_2023】3D Gaussian Splatting for Real-Time Radiance Field Rendering 一、前言Abstract1 INTRODUCTION2 RELATED WORK2.1 Traditional Scene Reconstruction and Rendering2.2 Neural Rendering and Radiance Fields2.3 Point-Based Rendering and Radiance Fields 3 O…

GPU设置

GPU降温测试 前提 同一个训练程序,使用8块GPU,GPU使用率基本全程>90%,GPU为1080 Ti 限制最高功率效果 不限制最高功率(默认最高功率250W):最高温度85,大多时间在75-85之间 将最高功率限制为150W:最高…

mtu 1500 qdisc noop state DOWN group default qlen 1000问题的解决

问题描述 1、打开虚拟机终端,root身份启动ens网卡(一般情况下还是会直接报错 ifup ens33 2、停止网卡设置disable再启动 systemctl stop NetworkManager 不报错即可 systemctl disable NetworkManagerservice network restart出现了绿色的OK啦&#…

SpringBoot——整合Shiro,实现安全认证和权限管理功能

目录 Shiro 项目总结 新建一个SpringBoot项目 pom.xml application.properties(配置文件) User(实体类) UserMapper(数据访问层接口) UserMapper.xml(数据库映射文件) User…

单位转换:将kb转换为 MB ,GB等形式

写法一&#xff1a; function formatSizeUnits(kb) {let units [KB, MB, GB, TB, PB,EB,ZB,YB];let unitIndex 0;while (kb > 1024 && unitIndex < units.length - 1) {kb / 1024;unitIndex;}return ${kb.toFixed(2)} ${units[unitIndex]}; } console.log(for…

北京站圆满结束!MongoDB Developer Day上海站,周六见!

上周六 MongoDB Developer Day首站北京站 80位开发者与MongoDB一起度过了充实的一天 专题讲座➕动手实操➕专家面对面交流 从数据建模、进阶查询技巧 到Atlas搜索与向量搜索 让参会伙伴们直呼“满满的技术干货&#xff01;” 全体参会者与工作人员合影 MongoDB Developer …

一个人 三个月 干了二十万

相信很多人是被这个标题吸引进来的&#xff0c;但我并不是标题党&#xff0c;我也很讨厌标题党&#xff0c;这篇文章也不在乎流量&#xff0c;更多的是想记录下。 出来创业三个多月了&#xff0c;给大家汇报一下这段时间的业绩吧。一个人&#xff0c;三个多月&#xff0c;干了…

数据分析报告制作的结构和思路整理

先画重点&#xff1a;一份分析报告的制作&#xff0c;目前的市场的分析步骤是优先找一些别人的研究报告&#xff0c;现成的东西&#xff0c;重点是要好好总结业务逻辑和潜在运营可能&#xff0c;这也是一位优秀数据分析师的价值体现。 举个例子&#xff0c;以目前小说短剧赛道的…

人工智能期末复习思维导图,参考人工智能及其应用(第6版)和柴玉梅老师教材

其中第一、六、七、八、九章不用重点看&#xff0c;计算题一般会考1.语义网络、谓词逻辑&#xff0c;2.可信度&#xff0c;3.主观贝叶斯&#xff0c;4.一般合一置换&#xff0c;5.证据理论&#xff0c;6.盲目搜索。 第一章&#xff1a;绪论 第二章&#xff1a;知识表示方法 第…

中小企业在数字化转型过程中遇到的挑战有哪些?

引言&#xff1a;中小企业推进数字化转型的背景是多重因素叠加的结果&#xff0c;包括市场竞争压力、信息技术发展及普及、各级政府政策支持及引导、企业经营发展需求和人才结构变化等。这些因素共同推动了中小企业加快数字化转型的步伐&#xff0c;以应对日益复杂多变的市场环…

2024年湖南建筑安全员考试题库,精准题库。

31.安全考核的对象应包括施工企业各管理层的&#xff08;&#xff09;、相关职能部门及岗位和工程项目参建人员。 A.技术负责人 B.安全负责人 C.主要负责人 D.第一负责人 答案&#xff1a;C 32.安全防护设施应标准化、定型化、&#xff08;&#xff09;。 A.规范化 B.工…