In continuation of the previous text 第5章:并发与竞态条件-9:The Spinlock Functions, let's GO ahead.
Reader/Writer Spinlocks
The kernel provides a reader/writer form of spinlocks that is directly analogous to the reader/writer semaphores we saw earlier in this chapter. These locks allow any number of readers into a critical section simultaneously, but writers must have exclusive access. Reader/writer locks have a type of rwlock_t, defined in . They can be declared and initialized in two ways:
内核提供的读写自旋锁,与本章前文介绍的读写信号量语义直接对应。这类锁允许任意数量的读线程同时进入临界区,但写线程必须独占访问。读写自旋锁的类型为 rwlock_t,定义于 <linux/spinlock.h> 头文件,可通过两种方式声明和初始化:
rwlock_t my_rwlock = RW_LOCK_UNLOCKED; /* Static way */
rwlock_t my_rwlock;
rwlock_init(&my_rwlock); /* Dynamic way */
The list of functions available should lookreasonably familiar by now. For readers, the following functions are available:
读线程的锁定与释放函数与普通自旋锁用法相近,如下所示:
void read_lock(rwlock_t *lock);
void read_lock_irqsave(rwlock_t *lock, unsigned long flags);
void read_lock_irq(rwlock_t *lock);
void read_lock_bh(rwlock_t *lock);
void read_unlock(rwlock_t *lock);
void read_unlock_irqrestore(rwlock_t *lock, unsigned long flags);
void read_unlock_irq(rwlock_t *lock);
void read_unlock_bh(rwlock_t *lock);
Interestingly, there is no read_trylock. The functions for write access are similar:
值得注意的是,读写自旋锁没有读非阻塞函数(read_trylock),写线程的函数与读线程类似,具体如下:
void write_lock(rwlock_t *lock);
void write_lock_irqsave(rwlock_t *lock, unsigned long flags);
void write_lock_irq(rwlock_t *lock);
void write_lock_bh(rwlock_t *lock);
int write_trylock(rwlock_t *lock);
void write_unlock(rwlock_t *lock);
void write_unlock_irqrestore(rwlock_t *lock, unsigned long flags);
void write_unlock_irq(rwlock_t *lock);
void write_unlock_bh(rwlock_t *lock);
Reader/writer locks can starve readers just as rwsems can. This behavior is rarely a problem; however, if there is enough lockcontention to bring about starvation, performance is poor anyway.
与读写信号量(rwsem)一样,读写自旋锁也可能导致读线程饥饿(即读线程长时间无法获取锁)。但这种情况通常不会造成严重问题:如果锁的竞争激烈到足以导致饥饿,系统性能本身已经很差了。
补充说明:
-
函数配对原则
读写自旋锁的函数必须严格配对使用,规则与普通自旋锁一致:例如
read_lock_irqsave必须与read_unlock_irqrestore配对,write_lock_bh必须与write_unlock_bh配对,否则可能导致中断或软中断状态异常。 -
与读写信号量(rwsem)的核心差异
特性
读写自旋锁(rwlock_t)
读写信号量(rwsem)
适用上下文
中断上下文、无睡眠进程上下文
仅进程上下文(可睡眠)
等待方式
自旋(忙循环)
阻塞睡眠
性能(无竞争)
极高
较低(有上下文切换开销)
读线程非阻塞
不支持(无 read_trylock)
支持(down_read_trylock)
-
无 read_trylock 的原因
内核设计中,读线程的非阻塞尝试(read_trylock)需求极少,且实现复杂度高(需处理多读者并发的原子性),因此未提供该接口。若需读线程非阻塞访问,可改用普通自旋锁或其他同步机制。
-
适用场景
读写自旋锁适用于 “读操作远多于写操作、且临界区极短” 的场景,例如:
-
中断上下文与进程上下文共享的只读数据保护。
-
驱动中共享数据的统计信息读取(读多写少);
-
-
饥饿问题的规避
若写操作频繁,应避免使用读写自旋锁,改用普通自旋锁或互斥锁,以防止读线程长期饥饿。
10万+

被折叠的 条评论
为什么被折叠?



