关闭

linux内核同步方式--自旋锁

标签: linux内核任务汇编linux
1262人阅读 评论(0) 收藏 举报
分类:

自旋锁:是linux内核中最常见的锁,自旋锁最多只能被一个可执行线程持有,如果一个执行线程试图获得一个被持有的自旋锁,那么该线程会一直进行忙循环,旋转,等待锁重新可用.


在任何时候,自旋锁都可以防止多于一个的执行线程同时进入临界区,一个被争用的自旋锁会导致请求他的线程在等待锁重新可用时自旋,所以自旋锁不应被长期持有.这也是自旋锁的初衷:在短期内进行轻量级加锁.
自旋锁的实现与体系结构密切相关,代码往往通过汇编实现.这些与体系结构相关的代码定义在<asm/spinlock.h>文件中,实际会使用到的接口是<linux/spinlock.h>文件中,自旋锁的基本使用形式是:
spinlock_t mr_lock = SPIN_LOCK_UNLOCKED;

spin_lock(&mr_lock);
/*
临界区
*/
spin_unlock(&mr_lock);
因为自旋锁同一时刻最多只能被一个执行线程持有,所以同一个时刻只会有一个线程处于临界区内,这就为多处理器提供了防止并发访问所需要的保护机制.

自旋锁也可以用在中断处理程序中,在中断处理程序使用自旋锁之前,一定要先进制本地中断,否则,中断处理程序就会打断正持有锁的内核代码,有可能会去争用这个被持有的自旋锁,但是锁的持有者在这个中断处理程序结束之前不能运行,从而造成了死锁.

内核提供的进制中断同时请求锁的接口:
spinlock_t mr_lock = SPIN_LOCK_UNLOCKED;

unsigned long flags;
spin_lock_irqsave(&mr_lock,flags);
/*
临界区
*/
spin_lock_irqrestore(&mr_lock,flags);
解释:
spin_lock_irqsave()保存中断的当前状态,并禁止本地中断,然后再去获得指定的锁,而spin_lock_irqrestore()是对指定的锁解锁,并让她恢复到加锁前的状态.

针对自旋锁的操作:
spin_lock_init()用来初始化动态创建的自旋锁,此时你只有一个指向spinlock_t类型的指针,并没有它的实体.
spin_try_lock()试图获得某个特定的自旋锁,如果该锁已经被争用,该方法会立刻返回一个非0值,而不会自旋等待锁被释放,如果成果获得了这个锁,那么就返回0.
spin_is_locked()方法和spin_try_lock()是一样的功效,该方法只做判断,并不生效.
spin_lock();//获取指定的自旋锁
spin_lock_irq();//禁止本地中断获取指定的锁
spin_lock_irqsave();//保存本地中断的状态,禁止本地中断,并获取指定的锁
spin_unlock();//释放指定的锁
spin_unlock_irq();//释放指定的锁,并激活本地中断
spin_unlock_irqrestore();//释放指定的锁,并让本地中断恢复到以前的状态
spin_lock_init();//初始化指定的spinlock_t
spin_try_lock();//试图获取指定的锁,如果未获取,则返回非0
spin_is_locked();//和try_lock()差不多

有很多时候锁的用途可以明确的分为读取和写入,比如说读写链表,因此linux就专门的提供了读-写自旋锁,这种锁为读和写分别提供了不同的锁:一个或多个读任务可以并发的持有读者锁,相反用于写的锁最多只能被一个写任务持有,而且此时不能有并发的读操作.

 

读/写自旋锁的使用方法类似于普通自旋锁,它们通过下面的方法初始化,具体的方法就不详细述说了.
需要注意的两点:自旋锁不能递归,防止死锁的产生.


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:1307367次
    • 积分:14707
    • 等级:
    • 排名:第782名
    • 原创:218篇
    • 转载:286篇
    • 译文:0篇
    • 评论:131条
    文章分类
    最新评论