博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
linux并发控制之读写信号量
阅读量:6268 次
发布时间:2019-06-22

本文共 2004 字,大约阅读时间需要 6 分钟。

读写信号量与信号量之间的关系类似于自旋锁与读写自旋锁。
读写信号量可能会引起进程阻塞,但是它允许N个读执行单元同时访问共享资源,而最多只允许有一个写执行单元访问共享资源;因此,读写信号量是一种相对放宽条件的、粒度稍大于信号量的互斥机制。
注意:
信号量不允许任何操作之间有并发。
理解:
定义于#include<linux/rwsem.h> 实际上在arch/X86/include/asm/rwsem.h 
其结构体为:
struct rw_semaphore {
long
count;
spinlock_t wait_lock;
struct list_head wait_list;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map dep_map;
#endif
};
其中读锁和写锁函数为:
static inline void __down_read(struct rw_semaphore *sem)
{
asm volatile("# beginning down_read\n\t"
    
 LOCK_PREFIX _ASM_INC  "(%1)\n\t"
     /* adds 0x00000001 */
     "  jns        1f\n"
     "  call call_rwsem_down_read_failed\n"    //跳转到rwsem_down_read_failed函数
     "1:\n\t"                  //给输出信息占位
     "# ending down_read\n\t"
     : "+m" (sem->count)
     : "a" (sem)
     : "memory", "cc");
}
static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
{
long tmp;
asm volatile("# beginning down_write\n\t"
     LOCK_PREFIX "  xadd      %1,(%2)\n\t"    //
xadd表示原操作数和目的操作数值相交换,而后相加保存入目的操作数
     /* adds 0xffff0001, returns the old value */
     "  test      %1,%1\n\t"            //
利用test指令检测count变量来实现
     /* was the count 0 before? */
     "  jz        1f\n"
     "  call call_rwsem_down_write_failed\n"
     "1:\n"
     "# ending down_write"
     : "+m" (sem->count), "=d" (tmp)
     : "a" (sem), "1" (RWSEM_ACTIVE_WRITE_BIAS)
     : "memory", "cc");
}
操作:
struct rw_semaphore rw_sem;                                     //定义读写信号量
void init_rwsem(struct rw_semaphore* rw_sem);       //初始化读写信号量
void down_read(struct rw_semaphore* rw_sem);            //获取读信号量
int down_read_trylock(struct rw_semaphore* rw_sem); //尝试获取读信号量
void up_read(struct rw_semaphore* rw_sem);             
void down_write(struct rw_semaphore* rw_sem);           //获取写信号量
int down_write_trylock(struct rw_semaphore* rw_sem);//尝试获取写信号量
void up_write(struct rw_semaphore* rw_sem);             
用例
rw_semaphore sem;   
init_rwsem(&sem);   
down_read(&sem);    
...临界区...          
up_read(&sem);     
down_write(&sem);   
...临界区...             
up_write(&sem);     
另:
void downgrade_write(struct rw_semaphore* sem);
该函数用于把写者降级为读者,有时,这是必要的。
因为写者是互斥的、排它的,因此在写者保护读写信号量期间,任何读者或写者都将无法访问该信号量所保护的共享资源,对于那些当前条件下不需要写操作的访问者,降级为写者,将使得等待访问的读者能够立即访问,从而增加了并发性,提高了效率。

转载于:https://www.cnblogs.com/hehehaha/archive/2013/01/31/6332971.html

你可能感兴趣的文章
vue part3.3 小案例ajax (axios) 及页面异步显示
查看>>
软件测试(二)之 Failure, Error & Fault
查看>>
浅谈MVC3自定义分页
查看>>
.net中ashx文件有什么用?功能有那些,一般用在什么情况下?
查看>>
select、poll、epoll之间的区别总结[整理]【转】
查看>>
CSS基础知识(上)
查看>>
PHP中常见的面试题2(附答案)
查看>>
角色权限分配
查看>>
明小子动力上传拿webshell.zip
查看>>
ES6 Module export与import复合使用
查看>>
第三篇、image 设置圆角的几种方式
查看>>
关于Vs2010 C#使用DirectX的问题
查看>>
EPP(Eclipse PHP)语法高亮仿EditPlus配置
查看>>
OA账号架构权限的问题
查看>>
030——VUE中鼠标语义修饰符
查看>>
python编辑csv
查看>>
sql游标的使用与exec的两种用法
查看>>
数据结构
查看>>
78/90 Subsets --back tracking
查看>>
非托管资源的释放
查看>>