信号量
一.信号量的实现
实际的信号量可以通过以下几种方法来声明和初始化
1. 直接创建信号量,通过 sema_init 完成
Void sema_init (struct semaphore *sem , int val);
其中val是赋予信号量的初始值。
2. 也可以用 DECLARE_MUTEX、DECLARE_MUTEX_LOCKED
DECLARE_MUTEX(name)、初始化为1
DECLARE_MUTEX_LOCKED(name) 初始化为0
3. 如果互斥体必须在运行时被初始化(例如在动态分配互斥体的情况下)应该使用下面的情况之一。
a) Void init_MUTEX(struct semaphore *sem);
b) Void init_MUTEX_LOCKED(struct semaphore *sem);
4. up和down操作
up(struct semaphore *sem);
void down(struct semaphore *sem);
int down_interruptible(struct semaphore *sem);
int down_trylock(struct semaphore *sem);
信号量会让调用者进入休眠状态,down_interruptible(struct semaphore *sem);是可以中断的,使用down_interruptible(struct semaphore *sem)需要格外的小心,如果操作被中断,该函数会返回非零值,而调用者不会拥有该信号量,使用时需要始终检查返回值,并作出相应的响应。而int down_trylock(struct semaphore *sem);永远不会休眠,如果信号量在调用的时候不可获得,down_trylock(struct semaphore *sem)会立即返回一个非零值。
二.信号量的使用
1. DECLARE_MUTEX(name);//1 例子摘自linux2.6.14 driver/i2c/i2c-core.c
static DECLARE_MUTEX(core_lists);
down(&core_lists);
……..
……..保护的内容
……..
up(&core_lists);
2. DECLARE_MUTEX_LOCKED(name) 初始化为0//driver/scsi/cpqfcTSworkor.c
DECLARE_MUTEX_LOCKED(fcQueReady);
down_interruptible( &fcQueReady); // wait for something to do
……
……
……
up( &fcQueReady );
没有明白初始化为0后,为什么又要down_interruptible( &fcQueReady),那这个操作不是不能操作吗?得不到信号量吗?又没有地方释放,那不是一直在哪里等啊?
3. 通过init_MUTEX 来初始化。
先定义一个信号量:
Struct semaphore sem;
初始化这个信号另:
Init_MUTEX(&sem);
现在就可以使用了:
Down(&sem);
……
……
……
Up(&sem);
NOTE:
在使用down操作的时候都可以针对情况选:
void down(struct semaphore *sem);
int down_interruptible(struct semaphore *sem);
int down_trylock(struct semaphore *sem);中的一种。
三、自旋锁
自旋锁可在不能休眠的代码中使用,比如在终端处理例程中。通常自旋锁能提供比信号量更高的性能。
<linux/spinlock.h>,
自旋锁的基本使用如下:
spinlock_t myr_lock = SPIN_LOCK_UNLOCKED; //也可在运行的时候初始化 //spin_lock_init(spinlock_t &myr_lock) spin_lock(&myr_lock); /*临界区*/ spin_unlock(&myr_lock); |