10.5 读-写信号量
信号量也有区分读-写访问的可能。读-写信号量比普通的信号量更具优势。
读-写信号量在内核中由rw_semaphore结构表示的,定义在文件<linux/rwsem.h>中。通过如下语句可以创建静态声明的读-写信号量:
static DECLARE_RWSEM(name);
其中name是新信号量名。
#define DECLARE_RWSEM(name) \
struct rw_semaphore name = __RWSEM_INITIALIZER(name)
动态创建的读-写信号量可通过如下函数初始化:
#define init_rwsem(sem) \
do { \
static struct lock_class_key __key; \
\
__init_rwsem((sem), #sem, &__key); \
} while (0)
所有的读-写信号量都是互斥信号量——它们的引用计数等于1,虽然它们只对写者互斥,不对读者。只要没有写者,并发持有读锁的读者数不限。相反,只有唯一的写者可以获得写锁。所有读-写锁的睡眠都不会被信号打断,所以它只有一个版本的down()操作。例如:
static DECLARE_RWSEM(rw_sem);
//试图获取信号量用于读...
down_read(&rw_sem);
//临界区(只读)
//释放信号量
up_read(&rw_sem);
//试图获取信号量用于写...
down_write(&rw_sem);
//临界区(读和写)
//释放信号量
up_write(&rw_sem);
读-写信号量也提供了down_read_trylock()和down_write_trylock()方法。这两个方法都需要一个指向读-写信号量的指针作为参数。如果成功获得了信号量锁,它们返回非0值;如果信号量锁被争用,则返回0。
读-写信号量相比读-写自旋锁多一种特有的操作:downgrade_write()。这个函数可以动态地将获取的写锁转换为读锁。
读-写信号量和读-写自旋锁一样,除非代码中的读和写可以明白无误地分割开来,否则,最好不使用它。读-写机制使用是有条件的,只有在你的代码可以自然地界定出读-写时才有价值。