由于Linux是一个支持多任务的操作系统,多个进程之间是一种并发的关系。并发是指在操作系统中,一个时间段中有几个程序都处于已启动运行到运行完毕之间,但在任一时间点上只有一个进程在处理器上运行。并发容易导致竞争的问题,竞争就是两个或两个以上的进程同时访问同一资源,从而引起资源的错误。这是操作系统运行所不允许的,所以内核中提供了一些并发控制的机制,用于对公共资源进行保护。
下面描述的相应机制的API都是ARM架构下的实现
(1) 原子操作
原子操作是一种在操作过程中不允许被打断的操作,所以在内核驱动程序中非常有用。原子操作需要硬件支持,所以是架构相关的
类型: atomic_t 定义在include/linux/types.h中
typedef struct {
int counter;
} atomic_t;
相关的API 实现在arch/arm/include/asm/atomic.h
18 #define ATOMIC_INIT(i) { (i) }
27 #define atomic_read(v) (*(volatile int *)&(v)->counter)
28 #define atomic_set(v,i) (((v)->counter) = (i)
37 static inline void atomic_add(int i, atomic_t *v)
38 {
39 unsigned long tmp;
40 int result;
41
42 __asm__ __volatile__("@ atomic_add\n"
43 "1: ldrex %0, [%3]\n"
44 " add %0, %0, %4\n"
45 " strex %1, %0, [%3]\n"
46 " teq %1, #0\n"
47 " bne 1b"
48 : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
49 : "r" (&v->counter), "Ir" (i)
50 : "cc");
51 }
75 static inline void atomic_sub(int i, atomic_t *v)
76 {
77 unsigned long tmp;
78 int result;
79
80 __asm__ __volatile__("@ atomic_sub\n"
81 "1: ldrex %0, [%3]\n"
82 " sub %0, %0, %4\n"
83 " strex %1, %0, [%3]\n"
84 " teq %1, #0\n"
85 " bne 1b"
86 : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
87 : "r" (&v->counter), "Ir" (i)
88 : "cc");
89 }
221 #define atomic_inc(v) atomic_add(1, v)
222 #define atomic_dec(v) atomic_sub(1, v)
223
224 #define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0)
225 #define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0)
226 #define atomic_inc_return(v) (atomic_add_return(1, v))
227 #define atomic_dec_return(v) (atomic_sub_return(1, v))
228 #define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
(2) 自旋锁
类型: spinlock_t 定义在include/linux/spinlock_types.h中
17 typedef struct {
18 volatile unsigned int slock;
19 } arch_spinlock_t;
20 typedef struct raw_spinlock {
21 arch_spinlock_t raw_lock;
22 #ifdef CONFIG_GENERIC_LOCKBREAK
23 unsigned int break_lock;
24 #endif
25 #ifdef CONFIG_DEBUG_SPINLOCK
26 unsigned int magic, owner_cpu;
27 void *owner;
28 #endif
29 #ifdef CONFIG_DEBUG_LOCK_ALLOC
30 struct lockdep_map dep_map;
31 #endif
32 } raw_spinlock_t;
64 typedef struct spinlock {
65 union {
66 struct raw_spinlock rlock;
67
68 #ifdef CONFIG_DEBUG_LOCK_ALLOC
69 # define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_map))
70 struct {
71 u8 __padding[LOCK_PADSIZE];
72 struct lockdep_map dep_map;
73 };
74 #endif
75 };
76 } spinlock_t;
相应的API操作函数 在include/linux/spinlock.h中
a>初始化锁
277 #define spin_lock_init(_lock) \
278 do { \
279 spinlock_check(_lock); \
280 raw_spin_lock_init(&(_lock)->rlock); \
281 } while (0)
103 # define raw_spin_lock_init(lock) \
104 do { *(lock) = __RAW_SPIN_LOCK_UNLOCKED(lock); } while (0)
59 #define __RAW_SPIN_LOCK_UNLOCKED(lockname) \
60 (raw_spinlock_t) __RAW_SPIN_LOCK_INITIALIZER(lockname)
53 #define __RAW_SPIN_LOCK_INITIALIZER(lockname) \
54 { \
55 .raw_lock = __ARCH_SPIN_LOCK_UNLOCKED, \
56 SPIN_DEBUG_INIT(lockname) \
57 SPIN_DEP_MAP_INIT(lockname) }
12 #define __ARCH_SPIN_LOCK_UNLOCKED { 1 }
spin_lock_init(spinlock_t *)
--> raw_spin_lock_init(raw_spinlock_t *)
--> __RAW_SPIN_LOCK_UNLOCKED(raw_spinlock_t *)
--> __RAW_SPIN_LOCK_INITIALIZER(raw_spinlock_t *)
--> __ARCH_SPIN_LOCK_UNLOCKED
实际上,也就是将锁初始化为1
b>请求锁
283 static inline void spin_lock(spinlock_t *lock)
284 {
285 raw_spin_lock(&lock->rlock);
286 }
170 #define raw_spin_lock(lock) _raw_spin_lock(lock)
135 void __lockfunc _raw_spin_lock(raw_spinlock_t *lock)
136 {
137 __raw_spin_lock(lock);
138 }
139 EXPORT_SYMBOL(_raw_spin_lock);
c> 解锁
323 static inline void spin_unlock(spinlock_t *lock)
324 {
325 raw_spin_unlock(&lock->rlock);
326 }
(3) 信号量
与自旋锁一样,信号量也是用来保护临界资源的一种方式
类型:struct semaphore 定义在include/linux/semaphore.h中
16 struct semaphore {
17 raw_spinlock_t lock;
18 unsigned int count;
19 struct list_head wait_list;
20 };
相关API
a> 定义一个信号量
29 #define DEFINE_SEMAPHORE(name) \
30 struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
b> 初始化一个信号量 (计数为1)
22 #define __SEMAPHORE_INITIALIZER(name, n) \
23 { \
24 .lock = __RAW_SPIN_LOCK_UNLOCKED((name).lock), \
25 .count = n, \
26 .wait_list = LIST_HEAD_INIT((name).wait_list), \
27 }
c> 请求信号量 (请求不到就sleep, 直到得到信号量或中断/kill signal才返回)
75 int down_interruptible(struct semaphore *sem)
101 int down_killable(struct semaphore *sem)
130 int down_trylock(struct semaphore *sem) //请求不到就返回,不进行sleep
d> 释放信号量
178 void up(struct semaphore *sem)