Linux內(nèi)核的同步機(jī)制_第1頁(yè)
Linux內(nèi)核的同步機(jī)制_第2頁(yè)
Linux內(nèi)核的同步機(jī)制_第3頁(yè)
Linux內(nèi)核的同步機(jī)制_第4頁(yè)
Linux內(nèi)核的同步機(jī)制_第5頁(yè)
已閱讀5頁(yè),還剩2頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、Linux內(nèi)核的同步機(jī)制一、引言在現(xiàn)代操作系統(tǒng)里,同一時(shí)間可能有多個(gè)內(nèi)核執(zhí)行流在執(zhí)行,因此內(nèi)核其實(shí)象多進(jìn)程多線程編程一樣也需要一些同步機(jī)制來同步各執(zhí)行單元對(duì)共享數(shù)據(jù)的訪問。尤其是在多處理器系統(tǒng)上,更需要一些同步機(jī)制來同步不同處理器上的執(zhí)行單元對(duì)共享的數(shù)據(jù)的訪問。在主流的Linux內(nèi)核中包含了幾乎所有現(xiàn)代的操作系統(tǒng)具有的同步機(jī)制,這些同步機(jī)制包括:原子操作、信號(hào)量(semaphore)、讀寫信號(hào)量(rw_semaphore)、spinlock、BKL(Big Kernel Lock)、rwlock、brlock(只包含在2.4內(nèi)核中)、RCU(只包含在2.6內(nèi)核中)和seqlock(只包含在2.

2、6內(nèi)核中)。二、原子操作所謂原子操作,就是該操作絕不會(huì)在執(zhí)行完畢前被任何其他任務(wù)或事件打斷,也就說,它的最小的執(zhí)行單位,不可能有比它更小的執(zhí)行單位,因此這里的原子實(shí)際是使用了物理學(xué)里的物質(zhì)微粒的概念。原子操作需要硬件的支持,因此是架構(gòu)相關(guān)的,其API和原子類型的定義都定義在內(nèi)核源碼樹的include/asm/atomic.h文件中,它們都使用匯編語(yǔ)言實(shí)現(xiàn),因?yàn)镃語(yǔ)言并不能實(shí)現(xiàn)這樣的操作。原子操作主要用于實(shí)現(xiàn)資源計(jì)數(shù),很多引用計(jì)數(shù)(refcnt)就是通過原子操作實(shí)現(xiàn)的。原子類型定義如下:typedef struct volatile int counter; atomic_t;volatile修

3、飾字段告訴gcc不要對(duì)該類型的數(shù)據(jù)做優(yōu)化處理,對(duì)它的訪問都是對(duì)內(nèi)存的訪問,而不是對(duì)寄存器的訪問。 原子操作API包括: atomic_read(atomic_t * v);該函數(shù)對(duì)原子類型的變量進(jìn)行原子讀操作,它返回原子類型的變量v的值。 atomic_set(atomic_t * v, int i);該函數(shù)設(shè)置原子類型的變量v的值為i。 void atomic_add(int i, atomic_t *v);該函數(shù)給原子類型的變量v增加值i。 atomic_sub(int i, atomic_t *v);該函數(shù)從原子類型的變量v中減去i。 int atomic_sub_and_test(in

4、t i, atomic_t *v);該函數(shù)從原子類型的變量v中減去i,并判斷結(jié)果是否為0,如果為0,返回真,否則返回假。 void atomic_inc(atomic_t *v);該函數(shù)對(duì)原子類型變量v原子地增加1。 void atomic_dec(atomic_t *v);該函數(shù)對(duì)原子類型的變量v原子地減1。 int atomic_dec_and_test(atomic_t *v);該函數(shù)對(duì)原子類型的變量v原子地減1,并判斷結(jié)果是否為0,如果為0,返回真,否則返回假。 int atomic_inc_and_test(atomic_t *v);該函數(shù)對(duì)原子類型的變量v原子地增加1,并判斷結(jié)果是

5、否為0,如果為0,返回真,否則返回假。 int atomic_add_negative(int i, atomic_t *v);該函數(shù)對(duì)原子類型的變量v原子地增加I,并判斷結(jié)果是否為負(fù)數(shù),如果是,返回真,否則返回假。 int atomic_add_return(int i, atomic_t *v);該函數(shù)對(duì)原子類型的變量v原子地增加i,并且返回指向v的指針。 int atomic_sub_return(int i, atomic_t *v);該函數(shù)從原子類型的變量v中減去i,并且返回指向v的指針。 int atomic_inc_return(atomic_t * v);該函數(shù)對(duì)原子類型的變量

6、v原子地增加1并且返回指向v的指針。 int atomic_dec_return(atomic_t * v);該函數(shù)對(duì)原子類型的變量v原子地減1并且返回指向v的指針。 原子操作通常用于實(shí)現(xiàn)資源的引用計(jì)數(shù),在TCP/IP協(xié)議棧的IP碎片處理中,就使用了引用計(jì)數(shù),碎片隊(duì)列結(jié)構(gòu)struct ipq描述了一個(gè)IP碎片,字段refcnt就是引用計(jì)數(shù)器,它的類型為atomic_t,當(dāng)創(chuàng)建IP碎片時(shí)(在函數(shù)ip_frag_create中),使用atomic_set函數(shù)把它設(shè)置為1,當(dāng)引用該IP碎片時(shí),就使用函數(shù)atomic_inc把引用計(jì)數(shù)加1。 當(dāng)不需要引用該IP碎片時(shí),就使用函數(shù)ipq_put來釋放該I

7、P碎片,ipq_put使用函數(shù)atomic_dec_and_test把引用計(jì)數(shù)減1并判斷引用計(jì)數(shù)是否為0,如果是就釋放IP碎片。函數(shù)ipq_kill把IP碎片從ipq隊(duì)列中刪除,并把該刪除的IP碎片的引用計(jì)數(shù)減1(通過使用函數(shù)atomic_dec實(shí)現(xiàn))。三、信號(hào)量(semaphore) Linux內(nèi)核的信號(hào)量在概念和原理上與用戶態(tài)的System V的IPC機(jī)制信號(hào)量是一樣的,但是它絕不可能在內(nèi)核之外使用,因此它與System V的IPC機(jī)制信號(hào)量毫不相干。信號(hào)量在創(chuàng)建時(shí)需要設(shè)置一個(gè)初始值,表示同時(shí)可以有幾個(gè)任務(wù)可以訪問該信號(hào)量保護(hù)的共享資源,初始值為1就變成互斥鎖(Mutex),即同時(shí)只能有一

8、個(gè)任務(wù)可以訪問信號(hào)量保護(hù)的共享資源。一個(gè)任務(wù)要想訪問共享資源,首先必須得到信號(hào)量,獲取信號(hào)量的操作將把信號(hào)量的值減1,若當(dāng)前信號(hào)量的值為負(fù)數(shù),表明無法獲得信號(hào)量,該任務(wù)必須掛起在該信號(hào)量的等待隊(duì)列等待該信號(hào)量可用;若當(dāng)前信號(hào)量的值為非負(fù)數(shù),表示可以獲得信號(hào)量,因而可以立刻訪問被該信號(hào)量保護(hù)的共享資源。當(dāng)任務(wù)訪問完被信號(hào)量保護(hù)的共享資源后,必須釋放信號(hào)量,釋放信號(hào)量通過把信號(hào)量的值加1實(shí)現(xiàn),如果信號(hào)量的值為非正數(shù),表明有任務(wù)等待當(dāng)前信號(hào)量,因此它也喚醒所有等待該信號(hào)量的任務(wù)。信號(hào)量的API有: API說明備注DECLARE_MUTEX(name)該宏聲明一個(gè)信號(hào)量name并初始化它的值為0,即聲

9、明一個(gè)互斥鎖。DECLARE_MUTEX_LOCKED(name)該宏聲明一個(gè)互斥鎖name,但把它的初始值設(shè)置為0,即鎖在創(chuàng)建時(shí)就處在已鎖狀態(tài)。因此對(duì)于這種鎖,一般是先釋放后獲得。void sema_init (struct semaphore *sem, int val);該函用于數(shù)初始化設(shè)置信號(hào)量的初值,它設(shè)置信號(hào)量sem的值為val。void init_MUTEX (struct semaphore *sem);該函數(shù)用于初始化一個(gè)互斥鎖,即它把信號(hào)量sem的值設(shè)置為1。void init_MUTEX_LOCKED (struct semaphore *sem);該函數(shù)也用于初始化一個(gè)

10、互斥鎖,但它把信號(hào)量sem的值設(shè)置為0,即一開始就處在已鎖狀態(tài)。void down(struct semaphore * sem);該函數(shù)用于獲得信號(hào)量sem,它會(huì)導(dǎo)致睡眠,因此不能在中斷上下文(包括IRQ上下文和softirq上下文)使用該函數(shù)。該函數(shù)將把sem的值減1,如果信號(hào)量sem的值非負(fù),就直接返回,否則調(diào)用者將被掛起,直到別的任務(wù)釋放該信號(hào)量才能繼續(xù)運(yùn)行。int down_interruptible(struct semaphore * sem);該函數(shù)功能與down類似,不同之處為,down不會(huì)被信號(hào)(signal)打斷,但down_interruptible能被信號(hào)打斷,因此該

11、函數(shù)有返回值來區(qū)分是正常返回還是被信號(hào)中斷,如果返回0,表示獲得信號(hào)量正常返回,如果被信號(hào)打斷,返回-EINTR。int down_trylock(struct semaphore * sem);該函數(shù)試著獲得信號(hào)量sem,如果能夠立刻獲得,它就獲得該信號(hào)量并返回0,否則,表示不能獲得信號(hào)量sem,返回值為非0值。因此,它不會(huì)導(dǎo)致調(diào)用者睡眠,可以在中斷上下文使用。void up(struct semaphore * sem);該函數(shù)釋放信號(hào)量sem,即把sem的值加1,如果sem的值為非正數(shù),表明有任務(wù)等待該信號(hào)量,因此喚醒這些等待者。信號(hào)量在絕大部分情況下作為互斥鎖使用,下面以console

12、驅(qū)動(dòng)系統(tǒng)為例說明信號(hào)量的使用。 在內(nèi)核源碼樹的kernel/printk.c中,使用宏DECLARE_MUTEX聲明了一個(gè)互斥鎖console_sem,它用于保護(hù)console驅(qū)動(dòng)列表console_drivers以及同步對(duì)整個(gè)console驅(qū)動(dòng)系統(tǒng)的訪問。 其中定義了函數(shù)acquire_console_sem來獲得互斥鎖 console_sem,定義了release_console_sem來釋放互斥鎖console_sem,定義了函數(shù) try_acquire_console_sem來盡力得到互斥鎖console_sem。這三個(gè)函數(shù)實(shí)際上是分別對(duì)函數(shù)down,up和 down_trylock的

13、簡(jiǎn)單包裝。 需要訪問console_drivers驅(qū)動(dòng)列表時(shí)就需要使用acquire_console_sem來保護(hù)console_drivers列表,當(dāng)訪問完該列表后,就調(diào)用release_console_sem釋放信號(hào)量console_sem。 函數(shù)console_unblank,console_device, console_stop,console_start,register_console和unregister_console都需要訪問 console_drivers,因此它們都使用函數(shù)對(duì)acquire_console_sem和release_console_sem來對(duì) consol

14、e_drivers進(jìn)行保護(hù)。四、讀寫信號(hào)量(rw_semaphore) 讀寫信號(hào)量對(duì)訪問者進(jìn)行了細(xì)分,或者為讀者,或者為寫者,讀者在保持讀寫信號(hào)量期間只能對(duì)該讀寫信號(hào)量保護(hù)的共享資源進(jìn)行讀訪問,如果一個(gè)任務(wù)除了需要讀,可能還需要寫,那么它必須被歸類為寫者,它在對(duì)共享資源訪問之前必須先獲得寫者身份,寫者在發(fā)現(xiàn)自己不需要寫訪問的情況下可以降級(jí)為讀者。讀寫信號(hào)量同時(shí)擁有的讀者數(shù)不受限制,也就說可以有任意多個(gè)讀者同時(shí)擁有一個(gè)讀寫信號(hào)量。如果一個(gè)讀寫信號(hào)量當(dāng)前沒有被寫者擁有并且也沒有寫者等待讀者釋放信號(hào)量,那么任何讀者都可以成功獲得該讀寫信號(hào)量;否則,讀者必須被掛起直到寫者釋放該信號(hào)量。如果一個(gè)讀寫信號(hào)

15、量當(dāng)前沒有被讀者或?qū)懻邠碛胁⑶乙矝]有寫者等待該信號(hào)量,那么一個(gè)寫者可以成功獲得該讀寫信號(hào)量,否則寫者將被掛起,直到?jīng)]有任何訪問者。因此,寫者是排他性的,獨(dú)占性的。讀寫信號(hào)量有兩種實(shí)現(xiàn),一種是通用的,不依賴于硬件架構(gòu),因此,增加新的架構(gòu)不需要重新實(shí)現(xiàn)它,但缺點(diǎn)是性能低,獲得和釋放讀寫信號(hào)量的開銷大;另一種是架構(gòu)相關(guān)的,因此性能高,獲取和釋放讀寫信號(hào)量的開銷小,但增加新的架構(gòu)需要重新實(shí)現(xiàn)。在內(nèi)核配置時(shí),可以通過選項(xiàng)去控制使用哪一種實(shí)現(xiàn)。讀寫信號(hào)量的相關(guān)API有:DECLARE_RWSEM(name)該宏聲明一個(gè)讀寫信號(hào)量name并對(duì)其進(jìn)行初始化。 void init_rwsem(struct rw

16、_semaphore *sem);該函數(shù)對(duì)讀寫信號(hào)量sem進(jìn)行初始化。 void down_read(struct rw_semaphore *sem);讀者調(diào)用該函數(shù)來得到讀寫信號(hào)量sem。該函數(shù)會(huì)導(dǎo)致調(diào)用者睡眠,因此只能在進(jìn)程上下文使用。 int down_read_trylock(struct rw_semaphore *sem);該函數(shù)類似于down_read,只是它不會(huì)導(dǎo)致調(diào)用者睡眠。它盡力得到讀寫信號(hào)量sem,如果能夠立即得到,它就得到該讀寫信號(hào)量,并且返回1,否則表示不能立刻得到該信號(hào)量,返回0。因此,它也可以在中斷上下文使用。 void down_write(struct rw

17、_semaphore *sem);寫者使用該函數(shù)來得到讀寫信號(hào)量sem,它也會(huì)導(dǎo)致調(diào)用者睡眠,因此只能在進(jìn)程上下文使用。 int down_write_trylock(struct rw_semaphore *sem);該函數(shù)類似于down_write,只是它不會(huì)導(dǎo)致調(diào)用者睡眠。該函數(shù)盡力得到讀寫信號(hào)量,如果能夠立刻獲得,就獲得該讀寫信號(hào)量并且返回1,否則表示無法立刻獲得,返回0。它可以在中斷上下文使用。 void up_read(struct rw_semaphore *sem);讀者使用該函數(shù)釋放讀寫信號(hào)量sem。它與down_read或down_read_trylock配對(duì)使用。如果do

18、wn_read_trylock返回0,不需要調(diào)用up_read來釋放讀寫信號(hào)量,因?yàn)楦揪蜎]有獲得信號(hào)量。 void up_write(struct rw_semaphore *sem);寫者調(diào)用該函數(shù)釋放信號(hào)量sem。它與down_write或down_write_trylock配對(duì)使用。如果down_write_trylock返回0,不需要調(diào)用up_write,因?yàn)榉祷?表示沒有獲得該讀寫信號(hào)量。 void downgrade_write(struct rw_semaphore *sem);該函數(shù)用于把寫者降級(jí)為讀者,這有時(shí)是必要的。因?yàn)閷懻呤桥潘缘模虼嗽趯懻弑3肿x寫信號(hào)量期間,任何讀

19、者或?qū)懻叨紝o法訪問該讀寫信號(hào)量保護(hù)的共享資源,對(duì)于那些當(dāng)前條件下不需要寫訪問的寫者,降級(jí)為讀者將,使得等待訪問的讀者能夠立刻訪問,從而增加了并發(fā)性,提高了效率。 讀寫信號(hào)量適于在讀多寫少的情況下使用,在linux內(nèi)核中對(duì)進(jìn)程的內(nèi)存映像描述結(jié)構(gòu)的訪問就使用了讀寫信號(hào)量進(jìn)行保護(hù)。 在Linux中,每一個(gè)進(jìn)程都用一個(gè)類型為task_t或struct task_struct的結(jié)構(gòu)來描述,該結(jié)構(gòu)的類型為struct mm_struct的字段mm描述了進(jìn)程的內(nèi)存映像,特別是mm_struct結(jié)構(gòu)的mmap字段維護(hù)了整個(gè)進(jìn)程的內(nèi)存塊列表,該列表將在進(jìn)程生存期間被大量地遍利或修改。 因此mm_struct結(jié)

20、構(gòu)就有一個(gè)字段mmap_sem來對(duì)mmap的訪問進(jìn)行保護(hù), mmap_sem就是一個(gè)讀寫信號(hào)量,在proc文件系統(tǒng)里有很多進(jìn)程內(nèi)存使用情況的接口,通過它們能夠查看某一進(jìn)程的內(nèi)存使用情況,命令free、ps 和top都是通過proc來得到內(nèi)存使用信息的,proc接口就使用down_read和up_read來讀取進(jìn)程的mmap信息。 當(dāng)進(jìn)程動(dòng)態(tài)地分配或釋放內(nèi)存時(shí),需要修改mmap來反映分配或釋放后的內(nèi)存映像,因此動(dòng)態(tài)內(nèi)存分配或釋放操作需要以寫者身份獲得讀寫信號(hào)量mmap_sem來對(duì)mmap進(jìn)行更新。系統(tǒng)調(diào)用brk和munmap就使用了down_write和 up_write來保護(hù)對(duì)mmap的訪問。

21、五、自旋鎖(spinlock) 自旋鎖與互斥鎖有點(diǎn)類似,只是自旋鎖不會(huì)引起調(diào)用者睡眠,如果自旋鎖已經(jīng)被別的執(zhí)行單元保持,調(diào)用者就一直循環(huán)在那里看是否該自旋鎖的保持者已經(jīng)釋放了鎖,自旋一詞就是因此而得名。由于自旋鎖使用者一般保持鎖時(shí)間非常短,因此選擇自旋而不是睡眠是非常必要的,自旋鎖的效率遠(yuǎn)高于互斥鎖。信號(hào)量和讀寫信號(hào)量適合于保持時(shí)間較長(zhǎng)的情況,它們會(huì)導(dǎo)致調(diào)用者睡眠,因此只能在進(jìn)程上下文使用(_trylock的變種能夠在中斷上下文使用),而自旋鎖適合于保持時(shí)間非常短的情況,它可以在任何上下文使用。如果被保護(hù)的共享資源只在進(jìn)程上下文訪問,使用信號(hào)量保護(hù)該共享資源非常合適,如果對(duì)共巷資源的訪問時(shí)間非

22、常短,自旋鎖也可以。但是如果被保護(hù)的共享資源需要在中斷上下文訪問(包括底半部即中斷處理句柄和頂半部即軟中斷),就必須使用自旋鎖。自旋鎖保持期間是搶占失效的,而信號(hào)量和讀寫信號(hào)量保持期間是可以被搶占的。自旋鎖只有在內(nèi)核可搶占或SMP的情況下才真正需要,在單CPU且不可搶占的內(nèi)核下,自旋鎖的所有操作都是空操作。跟互斥鎖一樣,一個(gè)執(zhí)行單元要想訪問被自旋鎖保護(hù)的共享資源,必須先得到鎖,在訪問完共享資源后,必須釋放鎖。如果在獲取自旋鎖時(shí),沒有任何執(zhí)行單元保持該鎖,那么將立即得到鎖;如果在獲取自旋鎖時(shí)鎖已經(jīng)有保持者,那么獲取鎖操作將自旋在那里,直到該自旋鎖的保持者釋放了鎖。無論是互斥鎖,還是自旋鎖,在任何

23、時(shí)刻,最多只能有一個(gè)保持者,也就說,在任何時(shí)刻最多只能有一個(gè)執(zhí)行單元獲得鎖。自旋鎖的API有:spin_lock_init(x)該宏用于初始化自旋鎖x。自旋鎖在真正使用前必須先初始化。該宏用于動(dòng)態(tài)初始化。 DEFINE_SPINLOCK(x)該宏聲明一個(gè)自旋鎖x并初始化它。該宏在2.6.11中第一次被定義,在先前的內(nèi)核中并沒有該宏。 SPIN_LOCK_UNLOCKED該宏用于靜態(tài)初始化一個(gè)自旋鎖。 DEFINE_SPINLOCK(x)等同于spinlock_t x = SPIN_LOCK_UNLOCKEDspin_is_locked(x)該宏用于判斷自旋鎖x是否已經(jīng)被某執(zhí)行單元保持(即被鎖)

24、,如果是,返回真,否則返回假。 spin_unlock_wait(x)該宏用于等待自旋鎖x變得沒有被任何執(zhí)行單元保持,如果沒有任何執(zhí)行單元保持該自旋鎖,該宏立即返回,否則將循環(huán)在那里,直到該自旋鎖被保持者釋放。 spin_trylock(lock)該宏盡力獲得自旋鎖lock,如果能立即獲得鎖,它獲得鎖并返回真,否則不能立即獲得鎖,立即返回假。它不會(huì)自旋等待lock被釋放。 spin_lock(lock)該宏用于獲得自旋鎖lock,如果能夠立即獲得鎖,它就馬上返回,否則,它將自旋在那里,直到該自旋鎖的保持者釋放,這時(shí),它獲得鎖并返回??傊挥兴@得鎖才返回。 spin_lock_irqsave

25、(lock, flags)該宏獲得自旋鎖的同時(shí)把標(biāo)志寄存器的值保存到變量flags中并失效本地中斷。 spin_lock_irq(lock)該宏類似于spin_lock_irqsave,只是該宏不保存標(biāo)志寄存器的值。 spin_lock_bh(lock)該宏在得到自旋鎖的同時(shí)失效本地軟中斷。 spin_unlock(lock)該宏釋放自旋鎖lock,它與spin_trylock或spin_lock配對(duì)使用。如果spin_trylock返回假,表明沒有獲得自旋鎖,因此不必使用spin_unlock釋放。 spin_unlock_irqrestore(lock, flags)該宏釋放自旋鎖lock

26、的同時(shí),也恢復(fù)標(biāo)志寄存器的值為變量flags保存的值。它與spin_lock_irqsave配對(duì)使用。 spin_unlock_irq(lock)該宏釋放自旋鎖lock的同時(shí),也使能本地中斷。它與spin_lock_irq配對(duì)應(yīng)用。 spin_unlock_bh(lock)該宏釋放自旋鎖lock的同時(shí),也使能本地的軟中斷。它與spin_lock_bh配對(duì)使用。 spin_trylock_irqsave(lock, flags)該宏如果獲得自旋鎖lock,它也將保存標(biāo)志寄存器的值到變量flags中,并且失效本地中斷,如果沒有獲得鎖,它什么也不做。 因此如果能夠立即獲得鎖,它等同于spin_loc

27、k_irqsave,如果不能獲得鎖,它等同于spin_trylock。如果該宏獲得自旋鎖lock,那需要使用spin_unlock_irqrestore來釋放。spin_trylock_irq(lock)該宏類似于spin_trylock_irqsave,只是該宏不保存標(biāo)志寄存器。如果該宏獲得自旋鎖lock,需要使用spin_unlock_irq來釋放。 spin_trylock_bh(lock)該宏如果獲得了自旋鎖,它也將失效本地軟中斷。如果得不到鎖,它什么也不做。因此,如果得到了鎖,它等同于spin_lock_bh,如果得不到鎖,它等同于spin_trylock。如果該宏得到了自旋鎖,需要

28、使用spin_unlock_bh來釋放。 spin_can_lock(lock)該宏用于判斷自旋鎖lock是否能夠被鎖,它實(shí)際是spin_is_locked取反。如果lock沒有被鎖,它返回真,否則,返回假。該宏在2.6.11中第一次被定義,在先前的內(nèi)核中并沒有該宏。 獲得自旋鎖和釋放自旋鎖有好幾個(gè)版本,因此讓讀者知道在什么樣的情況下使用什么版本的獲得和釋放鎖的宏是非常必要的。 如果被保護(hù)的共享資源只在進(jìn)程上下文訪問和軟中斷上下文訪問,那么當(dāng)在進(jìn)程上下文訪問共享資源時(shí),可能被軟中斷打斷,從而可能進(jìn)入軟中斷上下文來對(duì)被保護(hù)的共享資源訪問,因此對(duì)于這種情況,對(duì)共享資源的訪問必須使用spin_loc

29、k_bh和 spin_unlock_bh來保護(hù)。 當(dāng)然使用spin_lock_irq和spin_unlock_irq以及 spin_lock_irqsave和spin_unlock_irqrestore也可以,它們失效了本地硬中斷,失效硬中斷隱式地也失效了軟中斷。但是使用spin_lock_bh和spin_unlock_bh是最恰當(dāng)?shù)?,它比其他兩個(gè)快。 如果被保護(hù)的共享資源只在進(jìn)程上下文和tasklet或timer上下文訪問,那么應(yīng)該使用與上面情況相同的獲得和釋放鎖的宏,因?yàn)閠asklet和timer是用軟中斷實(shí)現(xiàn)的。 如果被保護(hù)的共享資源只在一個(gè)tasklet或timer上下文訪問,那么不需

30、要任何自旋鎖保護(hù),因?yàn)橥粋€(gè)tasklet或timer只能在一個(gè)CPU上運(yùn)行,即使是在SMP環(huán)境下也是如此。實(shí)際上tasklet在調(diào)用 tasklet_schedule標(biāo)記其需要被調(diào)度時(shí)已經(jīng)把該tasklet綁定到當(dāng)前CPU,因此同一個(gè)tasklet決不可能同時(shí)在其他CPU上運(yùn)行。 timer也是在其被使用add_timer添加到timer隊(duì)列中時(shí)已經(jīng)被幫定到當(dāng)前CPU,所以同一個(gè)timer絕不可能運(yùn)行在其他CPU上。當(dāng)然同一個(gè)tasklet有兩個(gè)實(shí)例同時(shí)運(yùn)行在同一個(gè)CPU就更不可能了。 如果被保護(hù)的共享資源只在兩個(gè)或多個(gè)tasklet或timer上下文訪問,那么對(duì)共享資源的訪問僅需要用spin_lock和spin_unlock來保護(hù),不必使用_bh版本,因?yàn)楫?dāng)tasklet或timer運(yùn)行時(shí),不可能有其他 tasklet或timer在當(dāng)前CPU

溫馨提示

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

評(píng)論

0/150

提交評(píng)論