znsoft
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2023-10-25
  • 粉丝300
  • 关注6
  • 积分910分
  • 威望14796点
  • 贡献值7点
  • 好评度2410点
  • 原创分5分
  • 专家分100分
  • 社区居民
  • 最爱沙发
  • 社区明星
阅读:2955回复:1

读写锁和顺序锁-[转帖] linux下的同步机制

楼主#
更多 发布于:2009-03-02 13:51
 读写锁,是自旋锁的一种衍生锁,为什么要衍生锁了,是因为自旋锁在多个执行单元在同时读写临界资源时都会被锁住,这样最多只能有一个执行单元拥有锁进而对资源进行操作,然而事实并非如此,在很多时候,同时读取临界资源是没有问题的,所以引入读写锁,他解决了读执行单元同时操作临界资源的问题,即允许读并发,但在写单元执行时最多允许一个进程访问临界资源。

定义和初始化:

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);




 
 
 
http://www.zndev.com 免费源码交换网 ----------------------------- 软件创造价值,驱动提供力量! 淡泊以明志,宁静以致远。 ---------------------------------- 勤用搜索,多查资料,先搜再问。
cyliu
论坛版主
论坛版主
  • 注册日期2003-06-13
  • 最后登录2014-04-11
  • 粉丝5
  • 关注0
  • 积分1238分
  • 威望2531点
  • 贡献值0点
  • 好评度577点
  • 原创分14分
  • 专家分10分
沙发#
发布于:2009-03-05 23:07
linux的锁好多种,各有个用途
走走看看开源好 Solaris vs Linux
游客

返回顶部