Linux驱动开发 -----互斥和同步(上)

本文探讨了Linux驱动开发中并发与并行的概念,重点讲解了处理竞态条件的五种机制:中断屏蔽、原子变量、自旋锁,并介绍了各自的特性和应用场景。在多处理器系统和中断处理中,这些机制对于确保内核数据的安全访问至关重要。
摘要由CSDN通过智能技术生成

并发与并行

并发是指一个处理器同时处理多个任务。
并行是指多个处理器或者是多核的处理器同时处理多个不同的任务。
并发是逻辑上的同时发生(simultaneous),而并行是物理上的同时发生。
来个比喻:并发是一个人同时吃三个馒头,而并行是三个人同时吃三个馒头。

并行(parallel):指在同一时刻,有多条指令在多个处理器上同时执行。就好像两个人各拿一把铁锨在挖坑,一小时后,每人一个大坑。所以无论从微观还是从宏观来看,二者都是一起执行的。

并发与竞态:

那些可能会引起竞态
1、多个应用层序(进程)访问驱动
2、对称多处理器(SMP)的多个CPU
3、单CPU内进程与抢占它的进程 Linux 2.6内核支持抢占调度,一个进程在内核执行的时候可能被另一高优先级进程打断,
进程与抢占它的进程访问共享资源的情况类似于SMP的多个CPU。
4、中断(硬中断、软中断、Tasklet、底半部)与进程之间中断可以打断正在执行的进程,
如果中断处理程序访问进程正在访问的资源,则竞态也会发生。

**

内核阶段如何去处理竞态: ---- 五套机制

1、中断屏蔽
2、原子变量
3、自旋锁
4、信号量
5、互斥体

不同的机制有不同的特点和应用场景。

1、中断屏蔽

屏蔽中断容易导致kenel down掉,不推荐使用,如果要使用的话,临界区的操作应尽可能的短
—>只能够屏蔽当前CPU
屏蔽中断
local_irq_disable() /* 屏蔽中断 /
critical section /
临界区*/
开启中断
local_irq_enable() /* 开中断*/

屏蔽中断的时候把中断状态保存
local_irq_save(flags)
critical section /* 临界区*/
开启中断,并回复中断状态
local_irq_restore(flags)

注意:local_irq_disable()和local_irq_enable()都只能禁止和使能本CPU内的中断,因此,并不能解决SMP多CPU引发的竞态

2、原子变量

特点:最小的可操作单位 原子操作 atomic 适用于变量,操作不可分割或被打断
atomic_t
本质:typedef struct {
int counter;
} atomic_t;
1、变量的定义
atomic_t myatomic;
2、变量的初始化
#define ATOMIC_INIT(i) { (i) }
#define atomic_set(v,i) (((v)->counter) = (i))
atomic_set(myatomic,1);
3、加锁-解锁
#define atomic_inc(v) atomic_add(1, v) //变量值加1
#define atomic_dec(v) atomic_sub(1, v) //变量值减1

#define atomic_inc_and_test(v)	(atomic_add_return(1, v) == 0)  //加1之后判断是否为0,
如果 == 0 为真,1,如果不为0,为假,0 
#define atomic_dec_and_test(v)	(atomic_sub_return(1, v) == 0)  //减1之后判断是否为0,
如果 == 0 为真,1,如果不为0,为假,0 
				static inline int atomic_add_return(int i, atomic_t *v)
						{
							unsigned long flags;
							int val;
							raw_local_irq_save(flags);
							val = v->counter;
							v->counter = val += i;
							raw_local_irq_restore(flags);
							return val;
						}
		--------解决什么问题啊? 举个例子(伪代码):

				多个进程同时控制灯,无法达到用户预期
				
				A : open    
							atomic_dec(1)    
								xxxxxdemo_ioctl   
								---------     =0
					close
							atomic_inc(v)	
					
				B :
					if(!atomic_dec_and_test(v)){
						printf("设备忙,等一等吧.\n");
						atomic_inc(v)
						return -EBUSY;
					}
	
				整合: 
					demo_open()
					{
						if(!atomic_dec_and_test(v)){
							printf("设备忙,等一等吧.\n");
							atomic_inc(v)
							return -EBUSY;
						}
						//atomic_dec(1);
					}
				
					demo_close()
					{
						atomic_inc(v)	
					}

代码实例(之前流水灯的代码):

#include <linux/module.h>
#include <linux/fs.h>

#include <linux/device.h>

#include <asm/uaccess.h>
#include <linux/io.h>
#include <linux/delay.h>

#include <asm/atomic.h>



#define FS4412LEDON  1
#define FS4412LEDOFF 0

#define GPX2CON   0x11000C40
#define GPX2_7DAT 0x11000c44
#define GPX1CON 0x11000c20
#define GPX1DAT 0x11000c24
#define GPF3CON 0x114001e0
#define GPF3DAT 0x114001e4

void __iomem * gpx2con_vir;
void __iomem * gpx2dat_
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值