信号量
信号量
信号量的引入
对于操作共享空间时间较长的场景,对于自旋锁的使用不太合适,自旋锁适用于快速完成的场景。因为自旋锁会关闭抢占与中断。
在执行完成之后,在开启中断与抢占。对于不能快速完成,等待时间较长的的场景,不适用于自旋锁。由此引入信号量机制,
而信号量机制的引入的特点,信号量可以使线程进入休眠。比如,对于共享内存。线程A与线程B都要访问,线程A正在访问共享内存期间,
如果线程B试图访问共享内存,如果采用信号量,线程B会进入休眠状态,等到锁被释放之后,休眠的线程B被唤醒,继续执行。如果采用自旋锁,线程B不会休眠,其在就绪状态,等待自旋锁释放。
信号量等待资源进程进入休眠状态,因此适用于资源占用比较久的场合
在中断中不能使用信号量,因为信号量会引起休眠,而中断是不能休眠的。
如果共享资源的持有时间较短,不适合信号量。频繁的休眠,唤醒切换比较占用时间。
信号量数据结构
信号量数据结构在文件:include/linux/semaphore.h
图 1 信号量数据结构
信号量操作的接口函数:
函数 |
描述 |
DEFINE_SEAMPHORE(name) |
定义一个信号量,并且设置信号量的值为 1。 |
void sema_init(struct semaphore *sem, int val) |
初始化信号量 sem,设置信号量值为 val。 |
void down(struct semaphore *sem) |
获取信号量,因为会导致休眠,因此不能在中 |
int down_trylock(struct semaphore *sem); |
尝试获取信号量,如果能获取到信号量就获 |
int down_interruptible(struct semaphore *sem) |
获取信号量,和 down 类似,只是使用
down 进 |
void up(struct semaphore *sem) |
释放信号量 |
信号量的使用
图 2 信号量的使用流程
如上图所示,信号量的使用流程。先初始化信号量:sema_init。进行信号量减1操作:down。
如果非负,获取临界区资源。执行完成之后,进行加1操作:up。