阅读:2955回复:1
读写锁和顺序锁-[转帖] linux下的同步机制
读写锁,是自旋锁的一种衍生锁,为什么要衍生锁了,是因为自旋锁在多个执行单元在同时读写临界资源时都会被锁住,这样最多只能有一个执行单元拥有锁进而对资源进行操作,然而事实并非如此,在很多时候,同时读取临界资源是没有问题的,所以引入读写锁,他解决了读执行单元同时操作临界资源的问题,即允许读并发,但在写单元执行时最多允许一个进程访问临界资源。
定义和初始化: rwlock_t my_rwlock=RW_LOCK_UNLOCKED; //静态初始化 rwlokc_t my_rwlock; rwlock_init(&my_rwlock); //动态初始化 读锁定与解锁: //读锁定与读解锁 void read_lock(rwlock_t *lock) void read_unlock(rwlock_t *lock) //相当于: read_lock()+local_irq_save()/local_irq_restore void read_lock_irqsave(rwlock_t *lock,unsigned long flags) void read_unlock_irqrestore(rwlock_t *lock,unsigned long flags) //相当于:read_lock()+local_irq_disable()/local_irq_enable() void read_lock_irq(rwlock_t *lock) void read_unlock_irq(rwlock_t *lock) //相当于:read_lock()+local_bh_disable()/local_bh_enable() void read_lock_bh(rwlock_t *lock) void read_unlock_bh(rwlock_t *lock) 写锁定与解锁: //写锁定与写解锁 void write_lock(rwlock_t *lock) void write_unlock(rwlock_t *lock) //相当于: write_lock()+local_irq_save()/local_irq_restore void write_lock_irqsave(rwlock_t *lock,unsigned long flags) void write_unlock_irqrestore(rwlock_t *lock,unsigned long flags) //相当于: write_lock()+local_irq_disable()/local_irq_enable() void write_lock_irq(rwlock_t *lock) void write_unlock_irq(rwlock_t *lock) //相当于: write_lock()+local_bh_disable()/local_bh_enable() void write_lock_bh(rwlock_t *lock) void write_unlock_bh(rwlock_t *lock) 另外还有:int write_trylock(rwlock_t *lock) ,不管成功与否,都会立即返回。 一般有如下用法模型: rwlock_t lock; //定义 read_init( &lock); ..........//临界资源 read_unlock(&lock); //写时 write_lock_irqsave(&lock,flags); ..........//临界资源 write_unlock_irqrestroe(&lock,flags); 顺序锁(seqlock_t),对读写锁的一种优化,使用顺序锁时,读不会被写执行单元阻塞,也就是说,当向一个临界资源中写入的同时,也可以从此临界资源中读取,即实现同时读写,但是同时写不被允许。如果读执行单元在读操作期间,写执行单元已经嗯发生了写操作,那么,读执行单元必须重新开始,这样保证了数据的完整性,当然这种可能是微乎其微。顺序锁的性能是非常好的,同时他允许读写同时进行,大大的提高了并发性。 但是他有一个限制:共享资源不含有指针,因为写执行单元可能使得指针失效,但读执行单元如果正要访问该指针,将导致Oops( 网上搜索这个词的意思是:吃惊的感叹词。我理解为访问该指针将会导致意想不到的结果)。 写执行单元涉及到的一些相关操作: void write_seqlock(seqlock_t *s1); void write_sequnlock(seqlock_t *s1); //宏调用,相当于:write_seqlock()+local_irq_save() write_seqlock_irqsave(lock,flags) write_sequnlock_irqrestore(lock,flags) //宏调用,相当于:write_seqlock()+local_irq+disable() write_seqlock_irq(lock) write_sequnlock_irq(lock) //宏调用,相当于:write_seqlock()+local_bh_disable() write_seqlock_bh(lock) write_sequnlock_bh(lock) int write_tryseqlock(seqlock_t *s1),此函数和上面提到的类似。 写执行单元使用如下一种模式的顺序锁: write_seqlock(&seqlock); .........//写操作代码块 write_sequnlock(&seqlock); 读执行单元涉及如下顺序锁操作: 读开始:unsigned read_seqbegin(const seqlock_t *s1);//读执行单元在访问共享资源时要//调用该函数,返回锁s1的顺序号, read_seqbegin_irqsave(lock,flags) //等同于:local_irq_save()+read_seqbegin() 重读:int read_seqretry(const seqlock_t *s1,unsigned iv) //在读结束后调用此函数来检///查,是否有写执行单元对资源进行操作,若有,则重新读。iv 为锁的顺序号。 代码段如下: do{ seqnum=read_seqbegin(&seqlock); //读操作代码段 ........... }while(read_seqretry(&seqlock,seqnum); |
|
|
沙发#
发布于:2009-03-05 23:07
linux的锁好多种,各有个用途
|
|
|