<dfn id="is4kg"></dfn>
  • <ul id="is4kg"></ul>
  • <abbr id="is4kg"></abbr>
  • <ul id="is4kg"></ul>
    <bdo id="is4kg"></bdo>

    Rss & SiteMap

    曙海教育集團論壇 http://www.bjzhda.cn

    曙海教育集團論壇
    共1 條記錄, 每頁顯示 10 條, 頁簽: [1]
    [瀏覽完整版]

    標題:Linux驅(qū)動程序開發(fā) - 內(nèi)核同步技術(shù)

    1樓
    wangxinxin 發(fā)表于:2010-11-24 9:20:31
    序言
    就像我們在操作系統(tǒng)里學(xué)習(xí)的那樣,如果多個程序(進程或線程)同時訪問臨界區(qū)數(shù)據(jù)就會發(fā)生競爭。存在競爭條件的程序會產(chǎn)生不可預(yù)料的結(jié)果。消除競爭的方法一般就是同步的訪問臨界區(qū)數(shù)據(jù)(原子訪問)。Linux內(nèi)核提供了多種技術(shù)用來實現(xiàn)內(nèi)核同步操作。下面我們就分別介紹。

    內(nèi)核同步技術(shù)
    Linux內(nèi)核是多進程、多線程的操作系統(tǒng),它提供了相當(dāng)完整的內(nèi)核同步方法。作為一個總結(jié),我們先列出內(nèi)核同步方法列表,這樣我們可以從總體上對內(nèi)核同步技術(shù)有個了解,然后我們這分別對每個同步技術(shù)做詳細介紹。
    同步技術(shù) 同步技術(shù)描述
    自旋鎖  
    讀寫自旋鎖  
     信號量  
    讀寫信號量
     
      原子操作
     
     內(nèi)存屏障  
      完成變量
     
     大內(nèi)核鎖  
    seq鎖
     

    鎖機制是一種廣泛使用的同步技術(shù),Linux內(nèi)核中最常見的鎖就是自旋鎖(spin lock)。自旋鎖被設(shè)計工作在多個處理器上(SMP),它只能被一個CPU上的一個進程(線程)所持有。它也可以工作在支持搶占的單處理器上。如果另一個進程或線程試圖獲取一個被持有的自旋鎖,那么它就會在該鎖上自旋(循環(huán)的執(zhí)行一小段代碼)直到該鎖被釋放。從這個意義上說,自旋鎖是忙等待的,這就會特別浪費處理器的時間,因此自旋鎖不應(yīng)該被長時間持有。對于單處理器并且不可搶占的內(nèi)核來說,自旋鎖什么也不作。
    需要強調(diào)的是,自旋鎖別設(shè)計用于多處理器的同步機制,對于單處理器,內(nèi)核在編譯時不會引入自旋鎖機制,對于可搶占的內(nèi)核,它僅僅被用于設(shè)置內(nèi)核的搶占機制是否開啟的一個開關(guān),也就是說加鎖和解鎖實際變成了禁止或開啟內(nèi)核搶占功能。如果內(nèi)核不支持搶占,那么自旋鎖根本就不會編譯到內(nèi)核中。
    內(nèi)核中使用spinlock_t類型來表示自旋鎖,它定義在<linux/spinlock_types.h>:

    typedef struct {
        raw_spinlock_t raw_lock;
    #if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP)
        unsigned int break_lock;
    #endif
    } spinlock_t;


    對于不支持SMP的內(nèi)核來說,struct raw_spinlock_t什么也沒有,是一個空結(jié)構(gòu)。對于支持多處理器的內(nèi)核來說,struct raw_spinlock_t定義為

    typedef struct {
        unsigned int slock;
    } raw_spinlock_t;


    slock表示了自旋鎖的狀態(tài),“1”表示自旋鎖處于解鎖狀態(tài)(UNLOCK),“0”表示自旋鎖處于上鎖狀態(tài)(LOCKED)。
    break_lock表示當(dāng)前是否由進程在等待自旋鎖,顯然,它只有在支持搶占的SMP內(nèi)核上才起作用。

    自旋鎖的實現(xiàn)是一個復(fù)雜的過程,說它復(fù)雜不是因為需要多少代碼或邏輯來實現(xiàn)它,其實它的實現(xiàn)代碼很少。自旋鎖的實現(xiàn)跟體系結(jié)構(gòu)關(guān)系密切,核心代碼基本也是由匯編語言寫成,與體協(xié)結(jié)構(gòu)相關(guān)的核心代碼都放在相關(guān)的<asm/>目錄下,比如<asm/spinlock.h>。對于我們驅(qū)動程序開發(fā)人員來說,我們沒有必要了解這么spinlock的內(nèi)部細節(jié),如果你對它感興趣,請參考閱讀Linux內(nèi)核源代碼。對于我們驅(qū)動的spinlock接口,我們只需包括<linux/spinlock.h>頭文件。在我們詳細的介紹spinlock的API之前,我們先來看看自旋鎖的一個基本使用格式:

    #include <linux/spinlock.h>
    spinlock_t lock = SPIN_LOCK_UNLOCKED;

    spin_lock(&lock);
    ....
    spin_unlock(&lock);


    從使用上來說,spinlock的API還很簡單的,一般我們會用的的API如下表,其實它們都是定義在<linux/spinlock.h>中的宏接口,真正的實現(xiàn)在<asm/spinlock.h>中

    #include <linux/spinlock.h>
    SPIN_LOCK_UNLOCKED
    DEFINE_SPINLOCK
    spin_lock_init( spinlock_t *)
    spin_lock(spinlock_t *)
    spin_unlock(spinlock_t *)
    spin_lock_irq(spinlock_t *)
    spin_unlock_irq(spinlock_t *)
    spin_lock_irqsace(spinlock_t *,unsigned long flags)
    spin_unlock_irqsace(spinlock_t *, unsigned long flags)
    spin_trylock(spinlock_t *)
    spin_is_locked(spinlock_t *)


    • 初始化
    spinlock有兩種初始化形式,一種是靜態(tài)初始化,一種是動態(tài)初始化。對于靜態(tài)的spinlock對象,我們用 SPIN_LOCK_UNLOCKED來初始化,它是一個宏。當(dāng)然,我們也可以把聲明spinlock和初始化它放在一起做,這就是 DEFINE_SPINLOCK宏的工作,因此,下面的兩行代碼是等價的。

    DEFINE_SPINLOCK (lock);
    spinlock_t lock = SPIN_LOCK_UNLOCKED;


    spin_lock_init 函數(shù)一般用來初始化動態(tài)創(chuàng)建的spinlock_t對象,它的參數(shù)是一個指向spinlock_t對象的指針。當(dāng)然,它也可以初始化一個靜態(tài)的沒有初始化的spinlock_t對象。

    spinlock_t *lock
    ......
    spin_lock_init(lock);


    • 獲取鎖
    內(nèi)核提供了三個函數(shù)用于獲取一個自旋鎖。
    spin_lock:獲取指定的自旋鎖。
    spin_lock_irq:禁止本地中斷并獲取自旋鎖。
    spin_lock_irqsace:保存本地中斷狀態(tài),禁止本地中斷并獲取自旋鎖,返回本地中斷狀態(tài)。

    自旋鎖是可以使用在中斷處理程序中的,這時需要使用具有關(guān)閉本地中斷功能的函數(shù),我們推薦使用 spin_lock_irqsave,因為它會保存加鎖前的中斷標志,這樣就會正確恢復(fù)解鎖時的中斷標志。如果spin_lock_irq在加鎖時中斷是關(guān)閉的,那么在解鎖時就會錯誤的開啟中斷。

    另外兩個同自旋鎖獲取相關(guān)的函數(shù)是:
    spin_trylock():嘗試獲取自旋鎖,如果獲取失敗則立即返回非0值,否則返回0。
    spin_is_locked():判斷指定的自旋鎖是否已經(jīng)被獲取了。如果是則返回非0,否則,返回0。
    • 釋放鎖
    同獲取鎖相對應(yīng),內(nèi)核提供了三個相對的函數(shù)來釋放自旋鎖。
    spin_unlock:釋放指定的自旋鎖。
    spin_unlock_irq:釋放自旋鎖并激活本地中斷。
    spin_unlock_irqsave:釋放自旋鎖,并恢復(fù)保存的本地中斷狀態(tài)。

    如果臨界區(qū)保護的數(shù)據(jù)是可讀可寫的,那么只要沒有寫操作,對于讀是可以支持并發(fā)操作的。對于這種只要求寫操作是互斥的需求,如果還是使用自旋鎖顯然是無法滿足這個要求(對于讀操作實在是太浪費了)。為此內(nèi)核提供了另一種鎖-讀寫自旋鎖,讀自旋鎖也叫共享自旋鎖,寫自旋鎖也叫排他自旋鎖。
    讀寫自旋鎖的使用也普通自旋鎖的使用很類似,首先要初始化讀寫自旋鎖對象:

    // 靜態(tài)初始化
    rwlock_t rwlock = RW_LOCK_UNLOCKED;
    //動態(tài)初始化
    rwlock_t *rwlock;
    ...
    rw_lock_init(rwlock);


    在讀操作代碼里對共享數(shù)據(jù)獲取讀自旋鎖:

    read_lock(&rwlock);
    ...
    read_unlock(&rwlock);


    在寫操作代碼里為共享數(shù)據(jù)獲取寫自旋鎖:

    write_lock(&rwlock);
    ...
    write_unlock(&rwlock);


    需要注意的是,如果有大量的寫操作,會使寫操作自旋在寫自旋鎖上而處于寫?zhàn)囸I狀態(tài)(等待讀自旋鎖的全部釋放),因為讀自旋鎖會自由的獲取讀自旋鎖。

    讀寫自旋鎖的函數(shù)類似于普通自旋鎖,這里就不一一介紹了,我們把它列在下面的表中。

    RW_LOCK_UNLOCKED
    rw_lock_init(rwlock_t *)
    read_lock(rwlock_t *)
    read_unlock(rwlock_t *)
    read_lock_irq(rwlock_t *)
    read_unlock_irq(rwlock_t *)
    read_lock_irqsave(rwlock_t *, unsigned long)
    read_unlock_irqsave(rwlock_t *, unsigned long)
    write_lock(rwlock_t *)
    write_unlock(rwlock_t *)
    write_lock_irq(rwlock_t *)
    write_unlock_irq(rwlock_t *)
    write_lock_irqsave(rwlock_t *, unsigned long)
    write_unlock_irqsave(rwlock_t *, unsigned long)
    rw_is_locked(rwlock_t *)


    信號量,或旗標,就是我們在操作系統(tǒng)里學(xué)習(xí)的經(jīng)典的P/V原語操作。
    P:如果信號量值大于0,則遞減信號量的值,程序繼續(xù)執(zhí)行,否則,睡眠等待信號量大于0。
    V:遞增信號量的值,如果遞增的信號量的值大于0,則喚醒等待的進程。

    信號量的值確定了同時可以有多少個進程可以同時進入臨界區(qū),如果信號量的初始值始1,這信號量就是互斥信號量(MUTEX)。對于大于1的非0值信號量,也可稱為計數(shù)信號量(counting semaphore)。對于一般的驅(qū)動程序使用的信號量都是互斥信號量。

    共1 條記錄, 每頁顯示 10 條, 頁簽: [1]

    Copyright © 2000 - 2009 曙海教育集團
    Powered By 曙海教育集團 Version 2.2
    Processed in .01563 s, 2 queries.
    主站蜘蛛池模板: 成年人网站免费观看| 男生吃女生的jiojio| 国语做受对白xxxxx在线| 久久夜色精品国产噜噜亚洲AV | 色噜噜狠狠一区二区三区| 国产高清视频网站| 中日韩精品视频在线观看| 日韩精品无码专区免费播放| 亚洲精品视频专区| 直接在线观看的三级网址| 国产免费人成视频在线观看| 777奇米四色成人影视色区| 大学生男男澡堂69gaysex| 丰满少妇弄高潮了www| 日韩人妻不卡一区二区三区| 亚洲精品免费在线| 男人让女人桶爽30分钟| 国产亚洲综合一区二区在线| 2021国产麻豆剧果冻传媒入口| 天天在线综合网| 丰满女邻居的嫩苞张开视频| 日韩a一级欧美一级| 亚洲大尺码专区影院| 激情无码人妻又粗又大| 四虎影院免费视频| 香港伦理电影三级中文字幕 | 亚洲成a人一区二区三区| 浮力国产第一页| 又硬又大又湿又紧a视频| 色老头在线一区二区三区| 国产精品久久久久电影| CAOPORN国产精品免费视频| 女神捕电影高清在线观看| 久久久噜噜噜久久熟女AA片| 日韩在线视频不卡| 亚洲日韩一页精品发布| 欧美精品免费在线| 你的腿再打开一点就能吃到了| 精品一区二区三区免费视频| 国产乱人伦偷精精品视频| 里番acg里番本子全彩|