本文转载自:http://blog.csdn.net/u012719256/article/details/52670098
信号量一般又叫做信号灯,协调不同进程间的数据对象的,本质上是一个计数器,记录对某个资源(共享内存)的存取情况。
从定义来看,信号量底层使用到了spin lock的锁定机制,这个spinlock主要用来确保对count成员的原子操作
使用的大致方式:
1)测试控制该资源的信号量
2)若此信号量为正,允许使用,进程将信号量-1
3)若信号量=0,则不可使用,进程进入睡眠状态,直到信号量大于0,进程被resume,jump to step1).
4)但进程不再使用一个信号量控制资源时,信号量+1,测试如果有进程正在等待此信号量,唤醒此进程。
解释:
信号量的获取:
(
1
).
void
down(
struct
semaphore *sem);
//废弃
在保证原子操作的前提下,先测试count是否大于0, ~ 如果是说明可以获得信号量,这种情况下需要先将count--,以确保别的进程能否获得该信号量,然后函数返回,其调用者开始进入临界区。 ~ 如果没有获得信号量,当前进程利用struct semaphore 中wait_list加入等待队列,开始睡眠。
(
2
).
int
down_interruptible(
struct
semaphore *sem);
/* 试图去获得一个信号量,如果没有获得,函数立刻返回1而不会让当前进程进入睡眠状态。 */
(
3
).
int
down_trylock(
struct
semaphore *sem);
/* 如果没有其他线程等待在目前即将释放的信号量上,那么只需将count++即可。如果有其他线程正因为等待该信号量而睡眠,那么调用__up唤醒睡眠的进程*/
void
up(
struct
semaphore *sem); //信号量的释放
互斥锁:
互斥主要现在了互相排斥(mutual exclusion)同步的简单形式,所以也叫mutex(互斥体)。
互斥体禁止多个线程同时进入受保护的代码临界区。因此,任何时刻,只有一个线程被允许进入这样的代码保护区
mutex实际上是count=1情况下的semaphore。而我们开发用的最多的锁就是mutex。
// 定义互斥锁lock
mutex_init(
struct
mutex*
lock
)
// 获取
mutex_lock(
struct
mutex *
lock
)
// 释放
mutex_unlock(
struct
mutex *
lock
)
// 结构
struct
mutex {
/* 1: unlocked, 0: locked, negative: locked, possible waiters */
atomic_t count;
spinlock_t wait_lock;
struct
list_head wait_list;
#ifdef CONFIG_DEBUG_MUTEXES
struct
thread_info *owner;
const
char
*name;
void
*magic;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct
lockdep_map dep_map;
#endif
};
自旋锁:
任何时刻,最多只能有一个保持者
区别于mutex:
对于mutex,如果资源已经被占用,资源的申请者只能进入suspend状态
但是自旋锁不会引起调用者suspend,如果自旋锁已经被别的单元持有,调用者会一直循环查看该锁是否释放(自旋的含义)
最大的区别,自旋锁不会suspend
结构:
# linux/Spinlock.h
typedef
struct
spinlock {
union {
//联合
struct
raw_spinlock rlock;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
# define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_map))
struct
{ u8 __padding[LOCK_PADSIZE];
struct
lockdep_map dep_map;
};
#endif
};
} spinlock_t;
init:
spinlock_t my_lock = SPIN_LOCK_UNLOCKED;
void
spin_lock_init(spinlock_t *
lock
);
自旋锁和互斥锁的对比:
信号量量/互斥体
允许进程睡眠属于
睡眠锁
,自旋锁则
不允许调用者睡眠
,而是让其
循环等待
,所以有以下区别应用
1)、信号量和读写信号量适合于保持时间较长的情况,它们会导致调用者睡眠,因而自旋锁适合于保持时间非常短的情况
2)、
自旋锁可以用于中断,不能用于
进程上下文
(会引起死锁)
。而
信号量不允许使用在中断中,而可以用于进程上下文
3)、自旋锁保持期间是抢占失效的,自旋锁被持有时,内核不能被抢占,而
信号量和读写信号量保持期间是可以被抢占的(意味着可以被中断)
使用场所:
信号量主要适用于进程间通信,当然,也可用于线程间通信。
而互斥锁只能用于线程间通信。