第7章 Linux并发控制-信号量

时间:2022-01-16 15:11:30

7.6 信号量

信号量(Semaphore)是操作系统中最典型的用于同步和互斥的手段,信号量的值可以是0、1或者n。信号量与操作系统中的经典概念PV操作对应。

P(S):

①将信号量S的值减1,即S=S-1;

②如果S≥0,则该进程继续执行;否则该进程置为等待状态,排入等待队列。

V(S):

①将信号量S的值加1,即S=S+1;

②如果S>0,唤醒队列中等待信号量的进程。

Linux中与信号量相关的操作主要有下面几种。

#include <linux/semaphore.h>

1.定义信号量

定义名称为sem的信号量:

struct semaphore sem;

2.初始化信号量

void sema_init(struct semaphore *sem, int val);

该函数初始化信号量,并设置信号量sem的值为val。

3.获得信号量

1)void down(struct semaphore * sem);// 可引起睡眠

该函数用于获得信号量sem,它会导致睡眠,不能在中断上下文中使用。

2)int down_interruptible(struct semaphore * sem);//能被信号打断

该函数功能与down类似,不同之处为,因为down()进入睡眠状态的进程不能被信号打断,但因为down_interruptible()进入睡眠状态的进程能被信号打断,信号也会导致该函数返回,这时候函数的返回值非0。

3)int down_trylock(struct semaphore * sem);// 非阻塞函数,不会睡眠。无法锁定资源则马上返回

该函数尝试获得信号量sem,如果能够立刻获得,它就获得该信号量并返回0,否则,返回非0值。它不会导致调用者睡眠,可以在中断上下文中使用。

注意:使用down_interruptible()获取信号量时,对返回值一般会进行检查,如果非0,通常立即返回-ERESTARTSYS,如:

if (down_interruptible(&sem))
    return  -ERESTARTSYS;

4.释放信号量

void up(struct semaphore * sem);

该函数释放信号量sem,唤醒等待者。

作为一种可能的互斥手段,信号量可以保护临界区,使用方式和自旋锁类似。与自旋锁相同,只有得到信号量的进程才能执行临界区代码。与自旋锁不同的是,当获取不到信号量时,进程不会原地打转而是进入休眠等待状态。

用作互斥时,信号量一般这样被使用:

第7章 Linux并发控制-信号量

第7章 Linux并发控制-信号量

由于新的Linux内核倾向于直接使用mutex作为互斥手段,信号量用作互斥不再被推荐使用。

信号量也可以用于同步,一个进程A执行down()等待信号量,另外一个进程B执行up()释放信号量,这样进程A就同步地等待了进程B。

第7章 Linux并发控制-信号量