昨天讲完了 mutex, semaphore ,今天仍要继续朝着各种不同的 lock前进,昨天讲的semaphore,有个明显的缺点,没办法知道在 C.S里的行程究竟是读还是写。 rwlock 可以有效的提高并行性,rwlock可以允许多个执行绪存取c.s 但是写入就只能有一个行程。
rwlock 具有以下的特性
rwlock 有两种,分别是 spinlock型与 semaphore型。
// <include/linux/rwlock_types.h >
typedef struct{
arch_rwlock_t raw_lock;
}rwlock_t
// <arch/arm/include/asm/spinlock_types.h>
typedef sturct{
u32 lock;
}arch_rwlock_t;
以下是常见的函数:
rwlock_init()
: 初始化rwlock。write_lock()
: 申请写入锁。write_unlock()
: 释放写入锁。read_lock()
: 申请读取锁。read_unlock()
:释放读取锁。read_lock_irq()
: 关闭中断并且申请读取锁。write_lock_irq()
:关闭中断并且申请写入锁。write_unlock_irq()
:打开中断并且释放写者锁。//<include/linux/rwsem.h>
struct rw_semaphore {
atomic_long_t count;
struct list_head wait_list;
raw_spinlock_t wait_lock;
#ifdef CONFIG_RWSEM_SPIN_ON_OWNER
struct optimistic_spin_queue osq; /* spinner MCS lock */
/*
* Write owner. Used as a speculative check to see
* if the owner is running on the cpu.
*/
struct task_struct *owner;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map dep_map;
#endif
};
wait_lock
: 是一个 spinlock变量,用以保护 rw_semaphore
资料结构中的 count
成员。
count
:用来保护 read-write semaphore 的计数。
wait_list
:管理所有在 semaphore上的睡眠行程,没有获取锁的行程会睡眠在这个链表。
osq
: 表示MCS锁。
owner
: 写者获取锁的时候, owner
指向锁持有者的 task_struct
资料结构。
其中将 count
拿出来看
/*
* the semaphore definition
*/
#ifdef CONFIG_64BIT
# define RWSEM_ACTIVE_MASK 0xffffffffL
#else
# define RWSEM_ACTIVE_MASK 0x0000ffffL
#endif
#define RWSEM_UNLOCKED_VALUE 0x00000000L
#define RWSEM_ACTIVE_BIAS 0x00000001L
#define RWSEM_WAITING_BIAS (-RWSEM_ACTIVE_MASK-1)
#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
count
应该要看成两段,分别为低位的 [15:0]位元,代表了正在持有锁的读取者或是写入者的个数; [31:16]为元,通常是一个负数,代表有一个正在持有锁或是处於等待状态的写入者,以及睡眠等待队列有人在等待。
例子如下
RWSEM_ACTIVE_READ_BIAS
= 0x00000001 ,即二元[0,1]表示只有一个读取者。RWSEM_ACTIVE_WRITE_BIAS
= 0xffff0001, 二元数[-1,1],表示当前只有一个活跃的写入者。RWSEM_WAITING_BIAS
= 0xffff0000 即[-1, 0]代表睡眠等待队列中有人在睡眠等待 。rw-lock 在kernel中应用广泛,特别是在内存管理经常会使用到除了前面的 mm->mmap_sem
的rw semaphore以外, RMAP系统中的 anon_vma->rwsem
、 address space 资料结构中的 i_mmap_rwsem
等。
最後再整理几个rw lock的重要特性:
down_read()
: 如果行程有了read lock,允许行程继续申请更多的 read lock,但是申请 write lock则需要睡眠等待down_write()
:如果一个行程有了 write lock ,另一个行程想申请 write lock 时,需要用 spinlock等待,申请 read lock 则需要睡眠等待。up_write()
/ up_read()
:若等待列上第一个成员是写入者,则只唤醒他; 若为读取行程,则唤醒等待列最前面几个连续的读取者。
>>: Day 25 : Linux - 如何在windows使用scp去传送档案至Linux上?
CSS 是前端开发者不可不学的技术之一,没有了它就好像你做出来的网页都没有穿衣服一样,有点羞於见人...
第10天,打完疫苗已经48小时,目前只有接种处抬手不会酸痛,昨天短暂晕完几分钟,就没感受到其他副作用...
有些公司永远在徵人(人员一直在流动),实际去应徵过後,会深刻理解到为什麽。 前几天提到GitHub时...
今天下班後去学校上课 回到家後就11点多了...... 就简单说明关於Gophish操作可能遇到的几...
前情提要 为了不浪费我白白画的春联,做了一个新年图制造机 还没有新年图的可以到下面玩玩看~(快收假了...