Linux信号量的实现(笔记)

来源:互联网 发布:体育比赛网络直播平台 编辑:程序博客网 时间:2024/06/07 19:57

一、普通信号量

Linux内核编程中要使用信号量,代码必须包括<asm/semaphore.h>头文件,信号量的结构体是struct semaphore,可以通过集中途径来声明和初始化。

一是直接创建信号量,通过void sema_init(struct semaphore *sem, int val);来完成,其中val是赋予信号量的初值。

 

更简单的是内核提供了一组辅助函数和宏:

DECLARE_MUTEX(name);//信号量name的值被初始化为1

DECLARE_MUTEX_LOCKED(name);//name的值被初始化为0

 

如果互斥体必须在运行时被初始化,应该使用下面的函数之一:

void init_MUTEX(struct semaphore *sem);

void init_MUTEX_LOCKED(struct semaphore *sem);

 

 

要获取信号量有三个版本的函数可以使用:

void down(struct semaphore *sem);

int down_interruptible(struct semaphore *sem);

int down_trylock(struct semaphore *sem);

 

down减小信号量的值,并在必要时一直等待。down_interruptible完成相同工作,但操作可中断。down_trylock永远不会休眠,如果信号量在调用时不可获得,那么会立即返回一个非零值。

 

 

归还信号量的是:

void up(struct semaphore *sem);

 

二、特殊信号量

Linux内核还提供了一种特殊的信号量:读者/写者信号量struct rw_semaphore,头文件是<linux/rwsem.h>。

该信号量的初始化必须通过以下函数显式的初始化:

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);

对于受保护资源的只读访问,多个读者可以并发访问,需要注意的是down_read_trylock在获得信号量时会返回非零值,这与其他大多数linux内核函数不同。

 

对于写者的接口:

void down_write(struct rw_semaphore *sem);

int down_write_trylock(struct rw_semaphore *sem);

void up_write(struct rw_semaphore *sem);

void downgrade_write(struct rw_semaphore *sem);

前三种与读者的对应函数行为相似。对于downgrade_write,当某个快速改变获得了写入者锁,而其后是更长时间的只读访问的话,可以在结束修改之后调用downgrade_write,来允许其他读者访问;也就是说,该函数把写者降级为读者,当写者在保持写信号量的期间,读者是无法访问被信号量保护的资源的,对于那些当前条件下不需要写访问的写者,可以通过该函数将其将为读者,使得等待访问的读者可以立刻访问,从而增加了并发性,提高了效率。

 

写者与读者相比拥有更高的优先级,当某个写者完成其工作之前,不会允许读者获得访问。