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