linux驅動 併發策略
互斥訪問:一個執行單元在訪問共享資源的時候,其他的執行單元被禁止訪問。
訊號量:在Liunx中的訊號量是一種睡眠鎖。假如程序A先持有訊號量F,然後程序B試圖獲取已經被程序A持有的訊號量F時(假如訊號量F資源值為1),訊號量會將B程序推入等待佇列,然後讓
其睡眠。當持有訊號量的程序A將訊號量F釋放後,程序B才會被喚醒,從而獲得這個訊號量,繼續執行程序B程式碼。
PS:訊號量的睡眠特性,使得訊號量適用於鎖會被長時間持有的情況;訊號量只能在程序中使用,不能再中斷中使用。
訊號量基本使用形式:
(1) 定義訊號量:struct semaphore sem;
(2) 初始化訊號量:void sema_init(struct semaphore *sem, int val);
(3) 初始化互斥訊號量:
void init_MUTEX(struct semaphore *sem);
等同於:sema_int(struct semaphore*sem, 1);
獲得訊號量:
(1) void down(struct semaphore *sem);
此函式用於獲得訊號量sem,它會導致睡眠,因此不能用於中斷上下文
(2) int down_interruptible(struct semaphore *sem);
同down(),差異在於因為down()而進入睡眠狀態的程序不能被訊號打斷,而因為down_interruptible()而進入睡眠狀態的程序能被訊號打斷,而訊號會導致該函式返回,這時候函式返回非0;
(3) int down_trylock(struct semaphore *sem);
該函式嘗試獲得訊號量sem,如果能夠立即獲得,它就獲得該訊號量返回0,否則,返回非0值,它不能導致呼叫者睡眠,可以在中斷上下文使用。
釋放訊號量:
void up(struct semaphore *sem);
該函式釋放訊號量sem,喚醒等待者。
使用訊號量的注意事項:
(1)可以長期加鎖;
(2)只能用於程序上下文,不能用於中斷上下文;
(3)在持有自旋鎖的同時,不能持有訊號量;
訊號量操作:
struct semaphore sem;//定義
static inline void sema_init(struct semaphore *sem,int val);//初始化
void down (struct semaphore *sem) ;// 獲取訊號量,沒獲取到就使當前程序睡眠
另外一個 downtrylock(struct semaphore *sem); 不睡眠 立即返回
extern void up (struct semaphore *sem);//釋放訊號量
原子操作:
atomic_t n; //定義一個原子變數
atomic_set(&n,2);//將變數初始值設為2
atmoic_add(5,&n);//將變數加5
atomic_dec(&n);//將變數減1
自旋鎖操作:
spinlock_t lock;//定義
spin_lock_init(&lock);//初始化
spin_lock(&lock);//獲取,沒獲取就被阻塞 spin_trylock(&lock)不阻塞 立即返回 成功返回非0 不成功返回0
臨界區程式碼
spin_unlock(&lock);//釋放
互斥體
互斥體實現了“互相排斥”(mutual exclusion)同步的簡單形式(所以名為互斥體
(mutex))。互斥體禁止多個執行緒同時進入受保護的程式碼“臨界區”(critical section)。因此,在任意時刻,只有一個執行緒被允許進入這樣的程式碼保護區。任何執行緒在進入臨界區之前,必須獲取(acquire)與此區域相關聯的互斥體的所有權。如果已有另一執行緒擁有了臨界區的互斥體,其他執行緒就不能再進入其中。這些執行緒必須等待,直到當前的屬主執行緒釋放(release)該互斥體。
使用;
struct mutex my_mutex;//定義
mutex_init(&my_mutex);//初始化
mutex_lock(struct mutex *lock) ;//另獲取外一個 mutex_trylock(struct mutex *lock)(沒獲取到也補睡眠,立即返回)
void mutex_unlock(struct mutex *lock);//釋放