您当前的位置:五五电子网电子知识单片机-工控设备嵌入式系统-技术Linux内核同步机制的自旋锁原理 正文
Linux内核同步机制的自旋锁原理

Linux内核同步机制的自旋锁原理

点击数:7572 次   录入时间:03-04 11:36:20   整理:http://www.55dianzi.com   嵌入式系统-技术

一、自旋锁

自旋锁是专为防止多处理器并发而引入的一种锁,它在内核中大量应用于中断处理等部分(对于单处理器来说,防止中断处理中的并发可简单采用关闭中断的方式,即在标志寄存器中关闭/打开中断标志位,不需要自旋锁)。

自旋就是自己连续的循环等待。如果你有抱着你的爱人旋转的经历,那么你应该知道一件事情,为了安全,你不能旋转太久,你的爱人如果头昏,也想你早日释放。是的,自旋的缺点,就是它频繁的循环直到等待锁的释放,将它用于可以快速完成的代码中才好。

自旋不能抢占,但能中断。
 
相关话题:SMP和cpu。多个cpu和单个cpu。很多书说自旋锁只能在多处理机中使用,这是不正确的。

首先定义
SPINLOCk_t lock;
对不起,我只能找到arm平台的锁了
/*
 * ARMv6 Spin-locking.
 *
 * We (exclusively) read the old value, and decrement it.  If it
 * hits zero, we may have won the lock, so we try (exclusively)
 * storing it.
 *
 * Unlocked value: 0
 * Locked value: 1
 */
typedef struct {
 volatile unsigned int lock;
#ifdef CONFIG_PREEMPT
 unsigned int break_lock;
#endif
} spinlock_t;
补上x86平台
#define SPINLOCK_MAGIC 0x1D244B3C
typedef struct {
 unsigned long magic;
 volatile unsigned long lock;
 volatile unsigned int babble;
 const char *module;    // 所属模块
 char *owner;
 int oline;
} spinlock_t;
Lock为0时可以用,1是等待。0像锁孔,当没有钥匙插进去时,它才可以插进去


怎么初始化呢?
#define spin_lock_init(x)
 do {
  (x)->magic = SPINLOCK_MAGIC;
  (x)->lock = 0;                ;0初始化,表示可用
  (x)->babble = 5;
  (x)->module = __FILE__;      
  (x)->owner = NULL;
  (x)->oline = 0;
 } while (0)
定义一个自旋锁的方法很有意思,
Spinlock_t lock=?????

可以通过spin_lock
Spin_lock_IRQsave 来调用自旋锁,后者不允许中断。前者有可能在上锁中发生中断。
还有spin_trylock 这是一个绝不妥协的函数,它不等待。


恢复为spin_unlock
Spin_unlock_irqrestore

考查下面代码
#define spin_lock_irqsave(lock, flags) _spin_lock_irqsave(lock, flags)
#define _spin_lock_irqsave(lock, flags)
do { 
 local_irq_save(flags);       保存中断请求标志
 preempt_dISAble();          不允许抢占
 _raw_spin_lock(lock);
 __acquire(lock);
} while (0)

二、自旋锁综合使用
下面是一个使用的例子,你可以使用source insight查到它
/* never calLED when PTRS_PER_PMD > 1 */
void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused)
{
 unsigned long flags; /* CAN be called from interrupt context */

 spin_lock_irqsave(&pgd_lock, flags);  枷锁
 pgd_list_del(pgd);
 spin_unlock_irqrestore(&pgd_lock, flags); 释放
}

中断枷锁
#define spin_lock_irqsave(lock, flags) _spin_lock_irqsave(lock, flags)
分析
unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock)
{
 unsigned long flags;

 local_irq_save(flags); 将寄存器存入flags,并关中断
 preempt_disable();   抢占锁
 _raw_spin_lock_flags(lock, flags);  枷锁
 return flags;
}
EXPORT_SYMBOL(_spin_lock_irqsave);


本文关键字:Linux  嵌入式系统-技术单片机-工控设备 - 嵌入式系统-技术