<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > Linux同步機制自旋鎖原理及其應(yīng)用

          Linux同步機制自旋鎖原理及其應(yīng)用

          作者: 時間:2012-04-05 來源:網(wǎng)絡(luò) 收藏

          一、

          是專為防止多處理器并發(fā)而引入的一種鎖,它在內(nèi)核中大量應(yīng)用于中斷處理等部分(對于單處理器來說,防止中斷處理中的并發(fā)可簡單采用關(guān)閉中斷的方式,即在標(biāo)志寄存器中關(guān)閉/打開中斷標(biāo)志位,不需要)。

          自旋就是自己連續(xù)的循環(huán)等待。如果你有抱著你的愛人旋轉(zhuǎn)的經(jīng)歷,那么你應(yīng)該知道一件事情,為了安全,你不能旋轉(zhuǎn)太久,你的愛人如果頭昏,也想你早日釋放。是的,自旋的缺點,就是它頻繁的循環(huán)直到等待鎖的釋放,將它用于可以快速完成的代碼中才好。

          本文引用地址:http://www.ex-cimer.com/article/257593.htm

          自旋不能搶占,但能中斷。

          相關(guān)話題: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像鎖孔,當(dāng)沒有鑰匙插進去時,它才可以插進去。

          怎么初始化呢?

          #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 來調(diào)用自旋鎖,后者不允許中斷。前者有可能在上鎖中發(fā)生中斷。
          還有spin_trylock 這是一個絕不妥協(xié)的函數(shù),它不等待。

          恢復(fù)為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); 保存中斷請求標(biāo)志
          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,并關(guān)中斷
          preempt_disable(); 搶占鎖
          _raw_spin_lock_flags(lock, flags); 枷鎖
          return flags;
          }
          EXPORT_SYMBOL(_spin_lock_irqsave);
          繼續(xù)
          /* For spinlocks etc */
          #define local_irq_save(x) __asm__ __volatile__(pushfl ; popl %0 ; cli:=g (x): /* no input */ :memory)
          將標(biāo)志寄存器的內(nèi)容放在內(nèi)存x中。請查看gcc匯編
          繼續(xù)
          static inline void _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
          {
          #ifdef CONFIG_DEBUG_SPINLOCK
          if (unlikely(lock->magic != SPINLOCK_MAGIC)) {
          printk(eip: %p , __builtin_return_address(0));
          BUG();
          }
          #endif
          __asm__ __volatile__(
          spin_lock_string_flags
          :=m (lock->slock) : r (flags) : memory);
          }
          繼續(xù)
          #define spin_lock_string_flags
          1:
          lock ; decb %0 ;lock總線鎖住,原子操作
          jns 4f
          2:
          testl $0x200, %1
          jz 3f
          sti
          3:
          rep;nop
          cmpb $0, %0
          jle 3b
          cli
          jmp 1b
          4:
          理解一下大概意思,就可以了。當(dāng)lock-1后大于等于0就可以關(guān)中斷繼續(xù)執(zhí)行了,否則nop空操作。Nop期間,cpu可以執(zhí)行其他任務(wù)的代碼。
          解鎖
          #define spin_unlock_irqrestore(lock, flags) _spin_unlock_irqrestore(lock, flags)
          void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
          {
          _raw_spin_unlock(lock);
          local_irq_restore(flags);
          preempt_enable();
          }
          static inline void _raw_spin_unlock(spinlock_t *lock)
          {
          #ifdef CONFIG_DEBUG_SPINLOCK
          BUG_ON(lock->magic != SPINLOCK_MAGIC);
          BUG_ON(!spin_is_locked(lock));
          #endif
          __asm__ __volatile__(
          spin_unlock_string
          );
          }
          Raw赤裸的解鎖,表示最低沉的解鎖原理。
          #define spin_unlock_string
          xchgb %b0, %1
          :=q (oldval), =m (lock->slock)
          :0 (oldval) : memory
          加1.解鎖

          linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)


          評論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();