Linux内核读写信号量实现

本文基于Linux kernel 3.10深入探讨读写信号量原理,阐述其允许同一时间一个写者或多个读者持有锁的特点,以及读写锁状态转换。详细解析了读写信号量的API,包括down_read、up_read、down_write和up_write的使用,并提及唤醒函数__rwsem_do_wake的关键作用。
摘要由CSDN通过智能技术生成

以下分析基于Linux kernel 3.10

读写信号量的原理

读写信号量的特点是:

1. 同一时刻最多有一个写者(writer)获得锁;

2. 同一时刻可以有多个读者(reader)获得锁;

3. 同一时刻写者和读者不能同时获得锁;

由于读者可以同时获得锁,因此提高了系统的并发程度,进而提高了系统的性能。

下图用状态转换图表示了在调用不同API时锁的相应状态。需要注意的是,锁的状态其实可以直接从读者有锁跳到写者有锁,例如有写者正sleep在down_write,而最后一个读者调用了up_read(),这时写者直接获得锁。


读写信号量的定义和API

参见文件include/linux/rwsem.h, 下面是读写信号量的定义和常用API。
struct rw_semaphore {
        long                    count;
        raw_spinlock_t          wait_lock;
        struct list_head        wait_list;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
        struct lockdep_map      dep_map;
#endif
};

#define init_rwsem(sem)                                         \
do {                                                            \
        static struct lock_class_key __key;                     \
                                                                \
        __init_rwsem((sem), #sem, &__key);                      \
} while (0)

extern void down_read(struct rw_semaphore *sem);
extern int down_read_trylock(struct rw_semaphore *sem);
extern void down_write(struct rw_semaphore *sem);
extern int down_write_trylock(struct rw_semaphore *sem);
extern void downgrade_write(struct rw_semaphore *sem);

extern void up_read(struct rw_semaphore *sem);
extern void up_write(struct rw_semaphore *sem);

从定义可以看出读写锁包含一个链表wait_list,它包含了所有等待该锁的task。wait_lock用于在多CPU情况下保护该链表。

1. 高16bits = 取补码(当前锁是否被写者获取() + 当前锁的等待链表非空())。如果当前锁被写者获取且等待链表非空,则高16bits应当等于(1+1)的补码,即0xfffe。如果链表为空,则高32bits等于(1+0)的补码,即0xffff。
2. 低16bits = 所有获取锁的写者加上获取锁的读者。如果有三个读者获取了锁,则低32bits等于3。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值