為了實(shí)現(xiàn)對(duì)臨界資源的有效管理,應(yīng)用層的程序有原子變量,條件變量,信號(hào)量來(lái)控制并發(fā),同樣的問(wèn)題也存在與驅(qū)動(dòng)開(kāi)發(fā)中,比如一個(gè)驅(qū)動(dòng)同時(shí)被多個(gè)應(yīng)用層程序調(diào)用,此時(shí)驅(qū)動(dòng)中的全局變量會(huì)同時(shí)屬于多個(gè)應(yīng)用層進(jìn)程的進(jìn)程空間,這種情況下也要使用一些技術(shù)來(lái)實(shí)現(xiàn)對(duì)并發(fā)的控制。本文將討論內(nèi)核中下述并發(fā)控制技術(shù)的技術(shù)特點(diǎn)和應(yīng)用場(chǎng)景。
中斷屏蔽
原子操作
原子變量操作
原子位操作
自旋鎖
傳統(tǒng)自旋鎖
讀寫(xiě)自旋鎖
順序鎖
RCU
信號(hào)量
傳統(tǒng)信號(hào)量
讀寫(xiě)信號(hào)量
完成量
互斥量
中斷屏蔽
顧名思義,就是屏蔽所有的中斷。在嵌入式系統(tǒng),中斷屏蔽可以有三級(jí),1. 硬件接口的屏蔽,2. 硬件GIC的屏蔽,3. CPU(內(nèi)核)的屏蔽。如果在接口處屏蔽了,那么中斷來(lái)了就丟了,根本找不到。如果在GIC處屏蔽了,那么在屏蔽期間如果來(lái)了irq_1,irq_2,irq_3個(gè)中斷,因?yàn)橹挥幸粋€(gè)pending標(biāo)志位,所以最后irq_3來(lái)的時(shí)候會(huì)將pending置位,之后解除屏蔽了,CPU發(fā)現(xiàn)pending有置位,還是會(huì)處理,但是1,2就肯定丟了。在ARM處的屏蔽,即內(nèi)核中的屏蔽,看怎么設(shè)置了,如果就是local_irq_disable,那么丟了就是丟了,和在接口處屏蔽一樣,如果是local_irq_save就和第二種一樣,追到最后一個(gè)中斷,內(nèi)核也有相應(yīng)的機(jī)制進(jìn)行中斷計(jì)數(shù),知道這期間來(lái)了多少個(gè)中斷,但是實(shí)際操作中,大部分情況我們都不會(huì)追著執(zhí)行錯(cuò)過(guò)的中斷,除非這個(gè)中斷非常重要。
我們這里討論的,就是在內(nèi)核中進(jìn)行中斷屏蔽。由于內(nèi)核中很多重要的操作都要依賴于中斷,所以屏蔽所有的中斷是十分危險(xiǎn)的,里面執(zhí)行的代碼要盡可能的快,而且,由于內(nèi)核的進(jìn)程調(diào)度也是由中斷驅(qū)動(dòng)的,所以中斷屏蔽中不能有可能引發(fā)休眠的代碼,否則無(wú)法被喚醒。注意,中斷屏蔽只是屏蔽了本CPU的中斷,所以并不能解決SMP引發(fā)的競(jìng)泰問(wèn)題,通常,中斷屏蔽要和自旋鎖聯(lián)合使用,用于防止訪問(wèn)自旋鎖保護(hù)的臨界區(qū)時(shí)被中斷打斷
普通的中斷屏蔽
local_irq_disable(); //屏蔽中斷//或local_irq_save(flags); //屏蔽中斷并保存目前CPU中的中斷位信息/* 臨界區(qū) */local_irq_enable(); //解除屏蔽//或local_irq_restore(flags); //解除屏蔽并恢復(fù)中斷位信息
底半部的中斷屏蔽
local_bh_disable(); //屏蔽中斷,bh版本的本質(zhì)是屏蔽了這個(gè)CPU上的軟中斷 /* 臨界區(qū) */local_bh_enable();