1、顺序锁seqlock的思想
对某一共享数据在读取的时候不加锁,写的时候加锁。
引入一顺序值sequence,读取者在开始读取前读取该变量的值,在读取后再次读取该值,如果两次读取的值不一致,说明在读取期间数据发生变化,读取无效。
写入者通过自旋锁做写入者之间的互斥。
每次写入前,将sequence值加1,写入之后,再次将sequence值加1。在学如过程中spinlock对其他写入者互斥。
2、seqlock的定义
typedef struct {
unsigned sequence;
spinlock_t lock;
} seqlock_t;
sequence 是顺序值,用来作读取数据有效无效的判断。
lock 是自旋锁,用来做写入者之间的互斥。
3、初始化
DEFINE_SEQLOCK(X) : 定义并初始化一个顺序锁
seqlock_init(x) :动态初始化一个顺序锁
4、写入者的操作
static inline void write_seqlock (seqlockt_t * sl)
获得顺序锁里的自旋锁
将sequence值加1
static inline void write_sequnlock(seqlock_t * sl)
将sequence值加1
解锁
static inline int write_trylock(seqlock_t * sl)
成功获得自旋锁返回 1 ,否则返回 0
5、读取者的操作
static __always_inline unsigned read_seqbegin(const seqlock_t *sl)
主要是获取seqence的值。如果遇到写操作正在进行,则不断循环等待写结束。
返回的是seqence的值。
static __always_inline int read_seqretry(const seqlock_t *sl, unsigned start)
start是用read_seqbegin获得的sequence的值。
如果本次读取无效,则返回 1 ,有效返回 0 。
读取者的代码实例:
unsigned start;
do {
start = read_seqbegin(&demo_seqlock);
do_read();
} while(read_seqretry(&demo_seqlock ,start ))
6、其他版本
write_seqlock_irq(lock)
write_seqlock_irqsave(lock,flags)
write_seqlock_bh(lock)
write_sequnlock_irq(lock)
write_sequnlock_irqrestore(lock,flags)
write_sequnlock_bh(lock)
read_seqbegin_irqsave(lock , flags)
read_seqretry_irqrestore(lock,iv,flags)
顺序锁seqlock与自旋读写锁rwlock的区别:
rwlock在写的时候与读取者和写入者都互斥
seqlock在写的时候只与写入者互斥
当要保护的资源很小,会很频繁被访问并且写入操作很少发生且快速时,可用seqlock