信号量
信号量允许多个进程同时进入临界区,大多数情况下只允许一个进程进入临界区,把信号量的计数值设置为1,即二值信号量,这种信号量称为互斥信号量。
和自旋锁相比,信号量适合保护比较长的临界区,因为竞争信号量时进程可能睡眠和再次唤醒,代价很高。
内核使用的信号量定义:
include/linux/semaphore.h
struct semaphore {
raw_spinlock_t lock; /* 自旋锁,用来保护信号量的其他成员 */
unsigned int count; /* 计数值,表示还可以允许多少个进程进入临界区 */
struct list_head wait_list; /* 等待进入临界区的进程链表 */
};
初始化静态信号量的方法:
(1)__SEMAPHORE_INITIALIZER(name, n):指定名称和计数值,允许n个进程同时进入临界区
(2)EFINE_SEMAPHORE(name):初始化一个互斥信号量
在运行时动态初始化信号量的方法:
static inline void sema_init(struct semaphore *sem, int val)
参数val指定允许同时进入临界区的进程数量。
获取信号量的函数:
(1)获取信号量,如果计数值是0,进程深度睡眠
void down(struct semaphore *sem);
(2)获取信号量,如果计数值是0,进程轻度睡眠
int down_interruptible(struct semaphore *sem);
(3)获取信号量,如果计数值是0,进程中度睡眠
int down_killable(struct semaphore *sem);
(4)获取信号量,如果计数值是0,进程不等待
int down_trylock(struct semaphore *sem);
(5)获取信号量,指定等待的时间
int down_timeout(struct semaphore *sem, long jiffies);
释放信号量的函数:
void up(struct semaphore *sem);