第二章1信號量及各種鎖_第1頁
第二章1信號量及各種鎖_第2頁
第二章1信號量及各種鎖_第3頁
第二章1信號量及各種鎖_第4頁
第二章1信號量及各種鎖_第5頁
已閱讀5頁,還剩24頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領

文檔簡介

NeusoftInstituteofInformation電子工程系--嵌入式Linux驅(qū)動設備開發(fā)目錄一并發(fā)與競態(tài)三自旋鎖、讀寫鎖四原子操作、等待隊列二信號量并發(fā)和它的管理

Linux系統(tǒng)的并發(fā)源:多個用戶空間進程在運行,它們可能以令人驚訝的方式組合運行你的代碼.SMP系統(tǒng)能夠同時在不同處理器上執(zhí)行你的代碼.內(nèi)核代碼是可搶占的;你的驅(qū)動代碼可能在任何時間失去處理器,代替它的進程可能也在你的驅(qū)動中運行.設備中斷是能夠?qū)е履愕拇a并發(fā)執(zhí)行的異步事件.內(nèi)核也提供各種延遲代碼執(zhí)行的機制,例如workqueue,tasklet,定時器.這些能夠使你的代碼在任何時間以一種與當前進程在做的事情無關(guān)的方式運行.資源共享的硬規(guī)則任何時候一個硬件或軟件資源被超出一個單個執(zhí)行線程共享,并且可能存在一個線程看到那個資源的不一致時,你必須明確地管理對那個資源的存取.

當內(nèi)核代碼創(chuàng)建一個會被內(nèi)核其他部分共享的對象時,這個對象必須一直存在(并且功能正常)到它知道沒有對它的外部引用存在為止.在大部分情況下,你將發(fā)現(xiàn)內(nèi)核為你處理引用計數(shù),但是常常有例外.信號量:是一個單個整型值,結(jié)合有一對函數(shù),典型地稱為P和V.一個想進入臨界區(qū)的進程將在相關(guān)信號量上調(diào)用P;如果信號量的值大于零,這個值遞減1并且進程繼續(xù).相反,如果信號量的值是0(或更小),進程必須等待(睡眠)直到別人釋放信號量.解鎖一個信號量通過調(diào)用V完成;這個函數(shù)遞增信號量的值,并且,如果需要,喚醒等待的進程.信號量和互斥體互斥:

阻止多個進程同時在同一個臨界區(qū)內(nèi)運行--它們的值將初始化為1.這樣的信號量在任何給定時間只能由一個單個進程或者線程持有.以這種模式使用的信號量有時稱為一個互斥鎖.

幾乎所有在Linux內(nèi)核中發(fā)現(xiàn)的信號量都用作互斥.

建立臨界區(qū):在任何給定時間只有一個線程可以執(zhí)行代碼.

信號量和互斥體信號量信號量在創(chuàng)建時需要設置一個初始值,表示允許有幾個任務同時訪問該信號量保護的共享資源,初始值為1就變成互斥鎖(Mutex),即同時只能有一個任務可以訪問信號量保護的共享資源。2.當任務訪問完被信號量保護的共享資源后,必須釋放信號量,釋放信號量通過把信號量的值加1實現(xiàn),如果釋放后信號量的值為非正數(shù),表明有任務等待當前信號量,因此要喚醒等待該信號量的任務。信號量的實現(xiàn)也是與體系結(jié)構(gòu)相關(guān)的,定義在<asm/semaphore.h>中,structsemaphore類型用來表示信號量。1.定義信號量structsemaphoresem;2.初始化信號量voidsema_init(structsemaphore*sem,intval)該函數(shù)用于初始化設置信號量的初值,它設置信號量sem的值為val。信號量信號量voidinit_MUTEX(structsemaphore*sem)該函數(shù)用于初始化一個互斥鎖,即它把信號量sem的值設置為1。voidinit_MUTEX_LOCKED(structsemaphore*sem)該函數(shù)也用于初始化一個互斥鎖,但它把信號量sem的值設置為0,即一開始就處在已鎖狀態(tài)。定義與初始化的工作可由如下宏一步完成:

DECLARE_MUTEX(name)定義一個信號量name,并初始化它的值為1。

DECLARE_MUTEX_LOCKED(name)定義一個信號量name,但把它的初始值設置為0,即鎖在創(chuàng)建時就處在已鎖狀態(tài)。信號量信號量獲取信號量 voiddown(structsemaphore*sem)獲取信號量sem,可能會導致進程睡眠,因此不能在中斷上下文使用該函數(shù)。該函數(shù)將把sem的值減1,如果信號量sem的值非負,就直接返回,否則調(diào)用者將被掛起,直到別的任務釋放該信號量才能繼續(xù)運行。intdown_interruptible(structsemaphore*sem)獲取信號量sem。如果信號量不可用,進程將被置為TASK_INTERRUPTIBLE類型的睡眠狀態(tài)。該函數(shù)由返回值來區(qū)分是正常返回還是被信號中斷返回,如果返回0,表示獲得信號量正常返回,如果被信號打斷,返回-EINTR。信號量信號量down_killable(structsemaphore*sem)獲取信號量sem。如果信號量不可用,進程將被置為TASK_KILLABLE類型的睡眠狀態(tài)。注:down()函數(shù)現(xiàn)已不建議繼續(xù)使用。建議使用down_killable()或down_interruptible()函數(shù)。信號量釋放信號量voidup(structsemaphore*sem)該函數(shù)釋放信號量sem,即把sem的值加1,如果sem的值為非正數(shù),表明有任務等待該信號量,因此喚醒這些等待者。自旋鎖自旋鎖最多只能被一個可執(zhí)行單元持有。自旋鎖不會引起調(diào)用者睡眠,如果一個執(zhí)行線程試圖獲得一個已經(jīng)被持有的自旋鎖,那么線程就會一直進行忙循環(huán),一直等待下去,在那里看是否該自旋鎖的保持者已經(jīng)釋放了鎖,“自旋”就是這個意思。自旋鎖spin_lock_init(x)該宏用于初始化自旋鎖x,自旋鎖在使用前必須先初始化。spin_lock(lock)獲取自旋鎖lock,如果成功,立即獲得鎖,并馬上返回,否則它將一直自旋在那里,直到該自旋鎖的保持者釋放。自旋鎖spin_trylock(lock)試圖獲取自旋鎖lock,如果能立即獲得鎖,并返回真,否則立即返回假。它不會一直等待被釋放。spin_unlock(lock)釋放自旋鎖lock,它與spin_trylock或spin_lock配對使用。信號量與自旋鎖的使用場合信號量可能允許有多個持有者,而自旋鎖在任何時候只能允許一個持有者。當然也有信號量叫互斥信號量(只能一個持有者),允許有多個持有者的信號量叫計數(shù)信號量。信號量適合于保持時間較長的情況;而自旋鎖適合于保持時間非常短的情況,在實際應用中自旋鎖控制的代碼只有幾行,而持有自旋鎖的時間也一般不會超過兩次上下文切換的時間,因為線程一旦要進行切換,就至少花費切出切入兩次,自旋鎖的占用時間如果遠遠長于兩次上下文切換,我們就應該選擇信號量。rwlock_t類型,在<linux/spinlokc.h>中定義初始化方法:

rwlock_tmy_rwlock=RW_LOCK_UNLOCKED; /*Staticway*/

rwlock_tmy_rwlock;

rwlock_init(&my_rwlock);/*Dynamicway*/允許多個讀進程同時進入臨界區(qū);寫進程必須互斥訪問臨界區(qū)。

讀寫鎖加鎖順序規(guī)則獲得多個鎖可能是危險的:Lock1和Lock2,代碼需要同時都獲取,你有一個潛在的死鎖.僅僅想象一個線程鎖住Lock1而另一個同時獲得Lock2.接著每個線程試圖得到它沒有的那個.2個線程都會死鎖.當多個鎖必須獲得時,它們應當一直以同樣順序獲得.

以相反的順序釋放。原子變量對共享變量n_opn_op++;都可能需要加鎖。內(nèi)核提供了一個原子整數(shù)類型稱為atomic_t

下面的操作為這個類型定義并且保證對于一個SMP計算機的所有處理器來說是原子的。因為它被編譯成一條單個機器指令voidatomic_set(atomic_t*v,inti);atomic_tv=ATOMIC_INIT(0);原子變量voidatomic_add(inti,atomic_t*v);voidatomic_sub(inti,atomic_t*v);voidatomic_inc(atomic_t*v);voidatomic_dec(atomic_t*v);intatomic_inc_and_test(atomic_t*v);intatomic_dec_and_test(atomic_t*v);intatomic_sub_and_test(inti,atomic_t*v);

voidset_bit(nr,void*addr);voidclear_bit(nr,void*addr);等待隊列在Linux驅(qū)動程序設計中,可以使用等待隊列來實現(xiàn)進程的阻塞,等待隊列可看作保存進程的容器,在阻塞進程時,將進程放入等待隊列,當喚醒進程時,從等待隊列中取出進程。Linux2.6內(nèi)核提供了如下關(guān)于等待隊列的操作:1、定義等待隊列wait_queue_head_tmy_queue2、初始化等待隊列init_waitqueue_head(&my_queue)3、定義并初始化等待隊列DECLARE_WAIT_QUEUE_HEAD(my_queue)等待隊列4、有條件睡眠wait_event(queue,condition)當condition(一個布爾表達式)為真時,立即返回;否則讓進程進入TASK_UNINTERRUPTIBLE模式的睡眠,并掛在queue參數(shù)所指定的等待隊列上。wait_event_interruptible(queue,condition)當condition(一個布爾表達式)為真時,立即返回;否則讓進程進入TASK_INTERRUPTIBLE的睡眠,并掛在queue參數(shù)所指定的等待隊列上。等待隊列intwait_event_killable(wait_queue_tqueue,condition)當condition(一個布爾表達式)為真時,立即返回;否則讓進程進入TASK_KILLABLE的睡眠,并掛在queue參數(shù)所指定的等待隊列上。等待隊列5、無條件睡眠(老版本,建議不再使用)sleep_on(wait_queue_head_t*q)讓進程進入不可中斷的睡眠,并把它放入等待隊列q。interruptible_sleep_on(wait_queue_head_t*q)讓

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論