中斷屏蔽 原子操作 信號量

在設計自己的驅動程序時,第一個要記住的規則是:只要可能,就應該避免資源的共享。若沒有併發訪問,就不會有競態。這種思想的最明顯的應用是避免使用全局變量。

臨界區:臨界區指的是一個訪問共用資源(例如:共用設備或是共用存儲器)的程序片段,而這些共用資源又無法同時被多個線程訪問的特性,臨界區同一時間只能被一個進程訪問


一、中斷屏蔽:
local_irq_disable()和local_irq_enable()都只能禁止和使能本CPU 內的中斷,因此,並不能解決SMP 多
CPU 引發的競態。因此,單獨使用中斷屏蔽通常不是一種值得推薦的避免競態的方法,它適宜與自旋鎖聯
合使用

    local_irq_disable() 和 local_irq_enable() 配對使用;只有我們知道中斷並未在其他地方被禁用的情況下,才能使用這個版        本

    local_irq_save() 和  local_irq_restore()  配對使用。
    local_irq_disable() 和 local_irq_save() 都可以禁止中斷,但不同的是後者可以保存中斷狀態。
    local_irq_restore() 在使能中斷的同時還恢復了由 local_irq_save() 所保存的中斷狀態。



二、原子操作:
UniProcessor單處理器平臺:因指令執行中不可能被插入,即使中斷也是在指令執行切換中再發生,所以原子操作沒必要。
SMP多處理器平臺:WINDOWS 用指令前綴lock用於鎖定前端串行總線(FSB)  linux atomic.h
目前來說內核中原子操作多用來做計數使用,其它情況最常用的是兩種鎖以及它們的變種:一個是自旋鎖,另一個是信號量。我們     下面就來着重介紹一下這兩種鎖機制。

   三、信號量

   ------------------------------------------------------
   Linux中的信號量是一種睡眠鎖。如果有一個任務試圖獲得一個已被持有的信號量時,信號量會將其推入等待隊列,然後讓其睡      眠。這時處理器獲得自由去執行其它代碼。當持有信號量的進程將信號量釋放後,在等待隊列中的一個任務將被喚醒,從而便可以    獲得這個信號量。
   信號量的睡眠特性,使得信號量適用於鎖會被長時間持有的情況;只能在進程上下文中使用,因爲中斷上下文中是不能被調度的;    另外當代碼持有信號量時,不可以再持有自旋鎖。

   信號量基本使用形式爲:
   static DECLARE_MUTEX(mr_sem);//聲明互斥信號量
   if(down_interruptible(&mr_sem))
   //可被中斷的睡眠,當信號來到,睡眠的任務被喚醒
   //臨界區
   up(&mr_sem);

  





信號量和自旋鎖區別
------------------------------------------------------
信號量適合於保持時間較長的情況,它們會導致調用者睡眠,因此只能在進程上下文使用自旋鎖適合於保持時間非常短的情況,它可以在任何上下文使用

自旋鎖保持期間是搶佔失效的,而信號量和讀寫信號量保持期間是可以被搶佔的。

自旋鎖不能遞歸使用

自旋鎖對信號量
------------------------------------------------------
需求 建議的加鎖方法

低開銷加鎖 優先使用自旋鎖
短期鎖定 優先使用自旋鎖
長期加鎖 優先使用信號量
中斷上下文中加鎖 使用自旋鎖
持有鎖是需要睡眠、調度 使用信號量

處理器總處於以下三種狀態之一:

1、內核態,運行於進程上下文,內核代表進程運行於內核空間;
2、內核態,運行於
中斷上下文,內核代表硬件運行於內核空間;
3、用戶態,運行於用戶空間。

用戶空間的應用程序,通過系統調用,進入內核空間。這個時候用戶空間的進程要傳遞 很多變量、參數的值給內核,內核態運行的時候也要保存用戶進程的一些寄存 器值、變量等。所謂的“進程上下文”,可以看作是用戶進程傳遞給內核的這些參數以及內核要保存的那一整套的變量和寄存器值和當時的環境等。

硬件通過觸發信號,導致內核調用中斷處理程序,進入內核空間。這個過程中,硬件的 一些變量和參數也要傳遞給內核,內核通過這些參數進行中斷處理。所謂的“ 中斷上下文”,其實也可以看作就是硬件傳遞過來的這些參數和內核需要保存的一些其他環境(主要是當前被打斷執行的進程環境)。

LINUX完全註釋中的一段話:

當一個進程在執行時,CPU的所有寄存器中的值、進程的狀態以及堆棧中的內容被稱 爲該進程的上下文。當內核需要切換到另一個進程時,它需要保存當前進程的 所有狀態,即保存當前進程的上下文,以便在再次執行該進程時,能夠必得到切換時的狀態執行下去。在LINUX中,當前進程上下文均保存在進程的任務數據結 構中。在發生中斷時,內核就在被中斷進程的上下文中,在內核態下執行中斷服務例程。但同時會保留所有需要用到的資源,以便中繼服務結束時能恢復被中斷進程 的執行。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章