信号量(semaphore)
//只有得到信号量的进程才能执行临界区代码;
//当获取不到信号量时,进程不会原地打转而是进入休眠等待状态。
1.定义信号量
struct semaphore sem;
- 初始化信号量
//初始化信号量,设置信号量sem的值为val。
void sema_init (struct semaphore *sem, int val);
void init_MUTEX(struct semaphore *sem);== sema_init (struct semaphore *sem, 1)
void init_MUTEX_LOCKED (struct semaphore *sem);== sema_init (struct semaphore *sem, 0)
//定义并初始化信号量的“快捷方式”。
DECLARE_MUTEX(name) //定义一个名为name的信号量并初始化为1。
DECLARE_MUTEX_LOCKED(name) //定义一个名为name的信号量并初始化为0。
- 获得信号量
//用于获得信号量sem。它会导致睡眠,进程不能被信号打断,因此不能在中断上下文使用。
void down(struct semaphore * sem);
//用于获得信号量sem。但进入睡眠状态的进程能被信号打断,对返回值一般会进行检查,如果非0,通常立即返回-ERESTARTSYS。
int down_interruptible(struct semaphore * sem);
//尝试获得信号量sem。如果能够立刻获得,它就获得该信号量并返回0;否则,返回非0值。
//不会导致调用者睡眠,可以在中断上下文使用。
int down_trylock(struct semaphore * sem);
4.释放信号量
//释放信号量sem,唤醒等待者。
void up(struct semaphore * sem);
##信号量典型用法##
DECLARE_MUTEX(mount_sem); //初始化
down(&mount_sem); //获取信号量,保护临界区
…
critical section //临界区
…
up(&mount_sem); //释放信号量
同步
//一个执行单元的继续执行需等待另一执行单元完成某事,保证执行的先后顺序。
- 初始化为0的信号量,可用于同步。
Example:执行单元A执行代码区域b前,必须等待执行单元B执行完代码区域c。
- 完成量(completion):一种比信号量更好的同步机制。
1) 定义完成量
struct completion my_completion;
2) 初始化completion
init_completion(&my_completion);
DECLARE_COMPLETION(my_completion); //初始化“快捷方式”
3) 等待完成量
void wait_for_completion(struct completion *c);
4) 唤醒完成量
//只唤醒一个等待的执行单元
void complete(struct completion *c);
//释放所有等待同一完成量的执行单元
void complete_all(struct completion *c);
Example:执行单元A执行代码区域b前,必须等待执行单元B执行完代码区域c。
读写信号量(rw_semaphore)
//允许n个读执行单元同时访问共享资源;但最多只能有一个写执行单元。
//可能引起进程阻塞。
- 定义和初始化读写信号量
struct rw_semaphore my_rws; // 定义读写信号量
void init_rwsem(struct rw_semaphore *sem); // 初始化读写信号量
- 读信号量获取/释放
void down_read(struct rw_semaphore *sem); //读信号量获取
int down_read_trylock(struct rw_semaphore *sem);
void up_read(struct rw_semaphore *sem); //读信号量释放
- 写信号量获取/释放
void down_write(struct rw_semaphore *sem); //写信号量获取
int down_write_trylock(struct rw_semaphore *sem);
void up_write(struct rw_semaphore *sem); //写信号量释放
##读写信号量典型用法##
rw_semaphore rw_sem; //定义读写信号量
init_rwsem(&rw_sem); //初始化读写信号量
//读时获取信号量
down_read(&rw_sem);
… //临界资源
up_read(&rw_sem);
//写时获取信号量
down_write(&rw_sem);
… //临界资源
up_write(&rw_sem);