1 Linux内核同步
Linux内核中有许多共享资源,这些共享资源是内核中进程都有机会访问到的。内核对其中一些共享资源的访问是独占的,因此需要提供机制对共享资源进行保护,确保任意时刻只有一个进程在访问共享资源。自旋锁就是一种共享资源保护机制,确保同一时刻只有一个进程能访问到共享资源。
2 普通自旋锁
内核中提供的普通自旋锁API为spin_lock()何spin_unlock(),使用的方法为:
spin_lock();
...临界区...
spin_unlock();
内核保证spin_lock()和spin_unlock()之间的临界区代码在任意时刻只会由一个CPU进行访问,并且当前CPU访问期间不会发生进程切换,当前进程也不会进入睡眠,这个在后面还会进一步分析。
3 单处理器(UP)普通自旋锁
之前讲过,自旋锁的功能有两点,一是临界区代码任意时刻由一个CPU进行访问,二是当前CPU访问期间不会发生进程切换。对于单处理器来说第一个问题就不存在了,因为只有一个CPU,不存在多处理器访问的问题。因此单处理器自旋锁只要保证CPU对临界区代码访问期间不发生进程切换就行了。知道了这一点后让我们来看看单处理器普通自旋锁使用的数据结构和API的实现代码。以下代码和数据结构使用的内核版本是Linux-2.6.24,特此注明。
3.1 数据结构
普通自旋锁的数据类型为spinlock_t:
typedef struct {
raw_spinlock_t raw_lock;
#if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP)
unsigned int break_lock;
#endif
#ifdef CONFIG_DEBUG_SPINLOCK
unsigned int magic, owner_cpu;
void *owner;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map dep_map;
#endif
} spinlock_t;
可以看出,去掉了编译配置选项之后其实spinlock_t里只剩下了类型为raw_spinlock_t的数据结构raw_lock: