分类: LINUX
2010-04-21 20:15:42
在内核中可以使用互斥锁来实现信号量行为。内核互斥锁是在原子 API 之上实现的,但这对于内核用户是不可见的。互斥锁很简单,但是有一些规则必须牢记。同一时间只能有一个任务持有互斥锁,而且只有这个任务可以对互斥锁进行 解锁。互斥锁不能进行递归锁定或解锁,并且互斥锁可能不能用于交互上下文。但是互斥锁比当前的内核信号量选项更快,并且更加紧凑,因此如果它们满足您的需 求,那么它们将是您明智的选择。
可以通过
DEFINE_MUTEX
宏使用一个操作创建和初始化互斥锁。这将创建一个新的互斥锁并初始化其结构。可以在
./linux/include/linux/mutex.h 中查看该实现。
DEFINE_MUTEX( my_mutex ); |
互斥锁 API 提供了 5 个函数:其中 3 个用于锁定,一个用于解锁,另一个用于测试互斥锁。首先看一下锁定函数。在需要立即锁定以及希望在互斥锁不可用时掌握控制的情形下,可以使用第一个函数 mutex_trylock
。
pthread_mutex_init
pthread_mutex_lock
pthread_mutex_trylock
pthread_mutex_unlock
pthread_mutex_destroy
ret = mutex_trylock( &my_mutex );
if (ret != 0) {
// Got the lock!
} else {
// Did not get the lock
}
|
当一个互斥锁被锁定后,它必须被解锁。这是由
mutex_unlock
函数来完成的。这个函数不能从中断上下文调用。最后,可以通过调用 mutex_is_locked
检查互斥锁的状态。这个调用实际上编译成一个内联函数。如果互斥锁被持有(锁定),那么就会返回 1;否则,返回 0。清单 12 演示了这些函数。
|
互斥锁 API 存在着自身的局限性,因为它是基于原子 API 的。但是其效率比较高,如果能满足你的需要,还是可以使用的。
在 Linux 中,pthread 库调用
pthread_mutex_lock()
和
pthread_mutex_trylock()
都可以用来获取互斥锁:
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
Linux 使用
pthread_mutex_unlock()
来释放互斥锁:
int pthread_mutex_unlock(pthread_mutex_t *mutex);
在 Linux 中,
pthread_mutex_destroy()
用来销毁一个互斥对象,并释放它持有的所有资源。这个调用还会检查当时这个互斥锁是否已经被释放了:
int pthread_mutex_destroy(pthread_mutex_t *mutex);
2.信号量
在 Linux 中,系统调用
sem_init()
用来创建一个 POSIX 信号量:
int sem_init(sem_t *sem, int pshared, unsigned int value);
其中
value
(信号量的计数)被设置为该信号量的初值。
Linux pthreads 使用
pthread_cond_init()
来创建一个条件变量:
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
pthread_cond_t
类型的条件变量可以使用常量
PTHREAD_COND_INITIALIZER
静态地进行初始化;还可以使用
pthread_condattr_init()
进行初始化,后者会对与这个条件变量有关的属性进行初始化。系统调用
pthread_condattr_destroy()
用来销毁属性:
Linux POSIX 信号量使用
sem_wait()
挂起调用线程,直到这个信号量的计数为非 0;然后自动减少这个信号量的计数:
int sem_wait(sem_t * sem)
在 POSIX 信号量中,没有超时功能。这可以在一个循环中执行非阻塞的
sem_trywait()
来实现,该循环可以计数超时值:
int sem_trywait(sem_t * sem);
Linux pthreads 使用
pthread_cond_wait()
来不确定地阻塞调用线程:
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
Linux POSIX 信号量使用
sem_post()
来释放事件信号量,这样可以唤醒一个正在因该信号量而阻塞的线程:
int sem_post(sem_t * sem);
pthread_cond_signal()
调用用来在 LinuxThreads 中唤醒正在等待这个条件变量的一个线程,而
pthread_cond_broadcast()
调用则用来唤醒正在等待这个条件变量的所有线程。
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
注意,条件函数不是异步信号安全的,不应该在信号处理函数中调用。在特殊情况下,如果在信号处理函数中调用
pthread_cond_signal
或
pthread_cond_broadcast
,可能会导致调用线程的死锁。
Linux POSIX 信号量使用
sem_destroy()
来销毁信号量:
int sem_destroy(sem_t * sem);
在 Linux pthreads 中,
pthread_cond_destroy()
用来销毁条件变量:
int pthread_cond_destroy(pthread_cond_t *cond);
HEV hevIpcInterrupt;
unsigned long ulPostCnt = 0;
unsigned long ulrc; // return code
unsigned long ulTimeout = 10 ; // timeout value
/* create event semaphore */
DosCreateEventSem (NULL, &hevIpcInterrupt, 0, TRUE);
/* In Thread A */
/* Wait forever for event to be posted */
DosWaitEventSem (hevIpcInterrupt, (unsigned long)
SEM_INDEFINITE_WAIT);
/* immediately unblocked as the semaphore is already posted */
/* Waits until the semaphore is posted */
DosWaitEventSem (hevIpcInterrupt, (unsigned long)
SEM_INDEFINITE_WAIT);
/* In Thread B */
DosPostEventSem(hevIpcInterrupt);
/* Close the semaphore */
ulrc = DosCloseEventSem (hevIpcInterrupt);