標籤:資源 共用資料 任務 延遲 isp cti gnu 中斷 tar
本文轉自自:http://www.jianshu.com/p/035550ae05d2
為什麼會產生並發
1、多個使用者同時登陸的時候,他們有可能在任何時刻以任意的組合調用核心代碼。
2、smp系統可能同時在不同的處理器上執行你的代碼。
3、核心代碼是搶佔式的,你的程式有可能隨時被剝奪掉處理器。
4、裝置中斷可能導致並發的非同步事件。
5、核心也提供了各種延遲代碼執行機制,如工作隊列等,任務隊列和定時器,它可以使你在與當前進程無關的方法中運行代碼
並髮帶來的影響
並發產生了競爭條件,比如兩個進程同時訪問相同的硬體資源
應對的基本原則是:盡量避免共用資料
如果無法避免那就一定要注意共用的資料。
Linux 的 訊號量
#include <linux/semaphore.h>
/** Copyright (c) 2008 Intel Corporation* Author: Matthew Wilcox <[email protected]>** Distributed under the terms of the GNU GPL, version 2** Please see kernel/semaphore.c for documentation of thesefunctions*/#ifndef __LINUX_SEMAPHORE_H#define __LINUX_SEMAPHORE_H#include <linux/list.h>#include <linux/spinlock.h>/* Please don‘t access any members of this structure directly */struct semaphore { raw_spinlock_t lock; unsigned int count; struct list_head wait_list;};#define __SEMAPHORE_INITIALIZER(name , n){ .lock = __RAW_SPIN_LOCK_UNLOCKED((name).lock), .count = n, .wait_list = LIST_HEAD_INIT((name).wait_list),} #define DEFINE_SEMAPHORE(name) struct semaphore name = __SEMAPHORE_INITIALIZER(name , 1)static inline void sema_init(struct semaphore *sem, int val){ static struct lock_class_key __key; *sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val); lockdep_init_map(&sem->lock.dep_map , "semaphore ->lock", &__key , 0);}extern void down(struct semaphore *sem);extern int __must_check down_interruptible(struct semaphore *sem);extern int __must_check down_killable(struct semaphore *sem);extern int __must_check down_trylock(struct semaphore *sem);extern int __must_check down_timeout(struct semaphore *sem, long jiffies);extern void up(struct semaphore *sem);#endif /* __LINUX_SEMAPHORE_H */
down方法將訊號量的值減一然後等到訊號量的值大於等於零繼續執行。
down_interruptible跟down類似但是可以被中斷,建議使用這個API,只使用down容易造成該線程永遠無法退出。
一般的使用方法是:
if (down_interruptible(&sem)) return -ERESTARTSYS;
讀寫訊號量
一種常見的訊號量,針對共用檔案,允許多個線程同時讀,而讀的時候不允許寫。在同一時間只允許一個線程寫。
#include <linux/rwsem.h>
自旋鎖
自旋鎖最初是為了SMP系統設計的,實現在多處理器情況下保護臨界區。
自旋鎖只有兩種狀態,上鎖,未上鎖,經常被用來確保一段代碼的原子性
spinlock API:
void spin_lock(spinlock_t *lock);void spin_lock_irqsave(spinlock_t *lock , unsigned long flags);void spin_lock_irq(spinlock_t *lock);void spin_lock_bh(spinlock_t *lock);
讀寫自旋鎖
linux核心提供了讀寫自旋鎖,實際上它與讀寫訊號量很相似。
上鎖的要求
1、如果你在自己的代碼裡實現了一個裝置鎖,而你也要套用到linux核心提供的鎖,請先把自己的鎖鎖上,再把系統的鎖鎖上。
2、如果你使用訊號量和自旋鎖,請先down訊號量,再使用自旋鎖。
3、確保自旋鎖內沒有其他的鎖,以防系統被死結。
Linux核心--並發【轉】