為什么會(huì)產(chǎn)生并發(fā)
1详幽、多個(gè)用戶同時(shí)登陸的時(shí)候筛欢,他們有可能在任何時(shí)刻以任意的組合調(diào)用內(nèi)核代碼。
2唇聘、smp系統(tǒng)可能同時(shí)在不同的處理器上執(zhí)行你的代碼版姑。
3、內(nèi)核代碼是搶占式的迟郎,你的程序有可能隨時(shí)被剝奪掉處理器剥险。
4、設(shè)備中斷可能導(dǎo)致并發(fā)的異步事件宪肖。
5表制、內(nèi)核也提供了各種延遲代碼執(zhí)行機(jī)制,如工作隊(duì)列等控乾,任務(wù)隊(duì)列和定時(shí)器么介,它可以使你在與當(dāng)前進(jìn)程無(wú)關(guān)的方法中運(yùn)行代碼
并發(fā)帶來(lái)的影響
并發(fā)產(chǎn)生了競(jìng)爭(zhēng)條件,比如兩個(gè)進(jìn)程同時(shí)訪問(wèn)相同的硬件資源
應(yīng)對(duì)的基本原則是:盡量避免共享數(shù)據(jù)
如果無(wú)法避免那就一定要注意共享的數(shù)據(jù)蜕衡。
Linux 的 信號(hào)量
#include <linux/semaphore.h>
/*
* Copyright (c) 2008 Intel Corporation
* Author: Matthew Wilcox <willy@linux.intel.com>
*
* Distributed under the terms of the GNU GPL, version 2
*
* Please see kernel/semaphore.c for documentation of these
functions
*/
#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方法將信號(hào)量的值減一然后等到信號(hào)量的值大于等于零繼續(xù)執(zhí)行壤短。
down_interruptible跟down類似但是可以被中斷,建議使用這個(gè)API慨仿,只使用down容易造成該線程永遠(yuǎn)無(wú)法退出久脯。
一般的使用方法是:
if (down_interruptible(&sem))
return -ERESTARTSYS;
讀寫(xiě)信號(hào)量
一種常見(jiàn)的信號(hào)量,針對(duì)共享文件镰吆,允許多個(gè)線程同時(shí)讀帘撰,而讀的時(shí)候不允許寫(xiě)。在同一時(shí)間只允許一個(gè)線程寫(xiě)鼎姊。
#include <linux/rwsem.h>
自旋鎖
自旋鎖最初是為了SMP系統(tǒng)設(shè)計(jì)的骡和,實(shí)現(xiàn)在多處理器情況下保護(hù)臨界區(qū)。
自旋鎖只有兩種狀態(tài)相寇,上鎖慰于,未上鎖,經(jīng)常被用來(lái)確保一段代碼的原子性
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);
讀寫(xiě)自旋鎖
linux內(nèi)核提供了讀寫(xiě)自旋鎖唤衫,實(shí)際上它與讀寫(xiě)信號(hào)量很相似婆赠。
上鎖的要求
1、如果你在自己的代碼里實(shí)現(xiàn)了一個(gè)設(shè)備鎖佳励,而你也要套用到linux內(nèi)核提供的鎖休里,請(qǐng)先把自己的鎖鎖上,再把系統(tǒng)的鎖鎖上赃承。
2妙黍、如果你使用信號(hào)量和自旋鎖,請(qǐng)先down信號(hào)量瞧剖,再使用自旋鎖拭嫁。
3、確保自旋鎖內(nèi)沒(méi)有其他的鎖抓于,以防系統(tǒng)被死鎖做粤。