linux随笔记 - 共享资源保护常用的几种方式

该笔记是学习左神或者伟神的教程的随笔记录,供需要时方便查阅,难免出错,还望指点。

资源保护原因:

linux并发访问时,可能存在多线程多核同时访问一段内存,造成数据混乱,所需要对资源进行保护,下面列举

1、多线程并发访问,Linux 是多任务(线程)的系统,所以多线程访问是最基本的原因。
2、抢占式并发访问,从 2.6 版本内核开始,Linux 内核支持抢占,也就是说调度程序可以
在任意时刻抢占正在运行的线程,从而运行其他的线程。
3、中断程序并发访问。
4、SMP(多核)核间并发访问,现在 ARM 架构的多核 SOC 很常见,多核 CPU 存在核间并发访问。

原子操作

原子操作简单来说就是在修改一个数据时,避免被打断,如下被打断的方式。

atomic_t v = ATOMIC_INIT(0); /* 定义并初始化原子变零 v=0 */
atomic_set(&v, 10); /* 设置 v=10 */
atomic_read(&v); /* 读取 v 的值,肯定是 10 */
atomic_inc(&v); /* v 的值加 1,v=11 */

自旋锁

自旋锁的“自旋”也就是“原地打转”的意思,“原地打转”的目的是为了等待自旋锁可以用,可以访问共享资源。

A获取到资源,释放之前,B想获取会原地循环等待。适用于轻量级加锁,很短时间的操作处理。(加锁期间禁止线程抢占,不然会存在锁死)
①、因为在等待自旋锁的时候处于“自旋”状态,因此锁的持有时间不能太长,一定要短,否则的话会降低系统性能。如果临界区比较大,运行时间比较长的话要选择其他的并发处理方式,比如稍后要讲的信号量和互斥体。
②、自旋锁保护的临界区内不能调用任何可能导致线程休眠的 API 函数,否则的话可能导致死锁。
③、不能递归申请自旋锁,因为一旦通过递归的方式申请一个你正在持有的锁,那么你就必须“自旋”,等待锁被释放,然而你正处于“自旋”状态,根本没法释放锁。结果就是自己把自己锁死了!
④、在编写驱动程序的时候我们必须考虑到驱动的可移植性,因此不管你用的是单核的还是多核的 SOC,都将其当做多核 SOC 来编写驱动程序

自旋锁可以在中断中使用,避免上了锁的任务被中断抢占,中断又在自旋,导致可能被锁死,那么就可以使用下列的带中断功能的自旋锁接口。

另外中断在一个大的系统中,无时无刻不再发生中断,更推荐带保存中断状态的自旋锁接口。

DEFINE_SPINLOCK(lock) /* 定义并初始化一个锁 */
/* 线程 A */
void functionA ()
{
	unsigned long flags; /* 中断状态 */
	spin_lock_irqsave(&lock, flags) /* 获取锁 */
	/* 临界区 */
	spin_unlock_irqrestore(&lock, flags)  /* 释放锁 */
}

 /* 中断服务函数 */
void irq() 
{
	spin_lock(&lock) /* 获取锁 */
	/* 临界区 */
	spin_unlock(&lock) /* 释放锁 */
}

信号量

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

struct semaphore sem; /* 定义信号量 */
sema_init(&sem, 1); /* 初始化信号量 */
down(&sem); /* 申请信号量 */
/* 临界区 */
up(&sem); /* 释放信号量 */

互斥体

互斥体大约可以理解为信号量值只有1的信号量。

在使用 mutex 之前要先定义一个 mutex 变量。在使用 mutex 的时候要注意如下几点:
1、mutex 可以导致休眠,因此不能在中断中使用 mutex,中断中只能使用自旋锁。
2、和信号量一样,mutex 保护的临界区可以调用引起阻塞的 API 函数。
3、因为一次只有一个线程可以持有 mutex,因此,必须由 mutex 的持有者释放 mutex。并且 mutex 不能递归上锁和解锁。

1 struct mutex lock; /* 定义一个互斥体 */
2 mutex_init(&lock); /* 初始化互斥体 */
3
4 mutex_lock(&lock); /* 上锁 */
5 /* 临界区 */
6 mutex_unlock(&lock); /* 解锁 */
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值