Simon 's Blog
» 做笔记做笔记
Toggle navigation
Simon 's Blog
HOME
总裁介绍
coper
zongcai
what
ARCH
TAGS
navigation
!!! 这是自旋锁吗???
? 同步互斥机制 ?
2017-10-13 17:55:13
596
0
0
simon88
? 同步互斥机制 ?
[TOC] 自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。互斥锁和自旋锁在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁。 # 自旋锁的缺点 自旋锁必须基于CPU的数据总线锁定,它通过读取一个内存单元(spinlock_t)来判断这个自旋锁是否已经被别的CPU锁住。如果否,它写进一个特定值,表示锁定了总线,然后返回。如果是,它会重复以上操作直到成功,或者spin次数超过一个设定值。记住上面提及到的:锁定数据总线的指令只能保证一个指令操作期间CPU独占数据总线。(自旋锁在锁定的时侯,不会睡眠而是会持续地尝试)。其作用是为了解决某项资源的互斥使用。因为自旋锁不会引起调用者睡眠,所以自旋锁的效率远高于互斥锁。虽然自旋锁的效率比互斥锁高,但是它也有些不足之处: - 自旋锁一直占用CPU,它在未获得锁的情况下,一直运行——自旋,所以占用着CPU,如果不能在很短的时间内获得锁,这无疑会使CPU效率降低。 - 在用自旋锁时有可能造成死锁,当递归调用时有可能造成死锁,调用有些其他函数(如`copy_to_user()`、`copy_from_user()`、`kmalloc()`等)也可能造成死锁。 因此我们要慎重使用自旋锁,*自旋锁只有在内核可抢占式或SMP的情况下才真正需要,在单CPU且不可抢占式的内核下,自旋锁的操作为空操作*。自旋锁适用于锁使用者保持锁时间比较短的情况。 # Linux自旋锁 先声明一个spinlock_t类型的自旋锁变量,并初始化为“未加锁”状态。在进入临界区之前,调用加锁函数获得锁,在退出临界区之前,调用解锁函数释放锁。例如: ```C spinlock_t lock = SPIN_LOCK_UNLOCKED; spin_lock(&lock); /* 临界区 */ spin_unlock(&lock); ``` 获得自旋锁和释放自旋锁的函数有多种变体,如下所示。 ```C spin_lock_irqsave/spin_unlock_irqrestore spin_lock_irq/spin_unlock_irq spin_lock_bh/spin_unlock_bh/spin_trylock_bh ``` 上面各组函数最终都需要调用自旋锁操作函数。spin_lock函数用于获得自旋锁,如果能够立即获得锁,它就马上返回,否则,它将自旋在那里,直到该自旋锁的保持者释放。spin_unlock函数则用于释放自旋锁。此外,还有一个spin_trylock函数用于尽力获得自旋锁,如果能立即获得锁,它获得锁并返回真;若不能立即获得锁,立即返回假。它不会自旋等待自旋锁被释放。 自旋锁使用时有两点需要注意: - 自旋锁是不可递归的。 - 线程获取自旋锁之前,要禁止当前处理器上的中断。(防止获取锁的线程和中断形成竞争条件) # DPDK自旋锁 DPDK中自旋锁API的定义在rte_spinlock.h文件中,其中下面三个API被广泛的应用在告警、日志、中断机制、内存共享和link bonding的代码中,用于临界资源的保护。 ```c rte_spinlock_init(rte_spinlock_t *sl); rte_spinlock_lock(rte_spinlock_t *sl); rte_spinlock_unlock(rte_spinlock_t *sl); ``` 其中rte_spinlock_t定义如下,简洁并且简单。 ```c /** * The rte_spinlock_t type. */ typedef struct { volatile int locked;/**< lock status 0 = unlocked, 1 = locked */ } rte_spinlock_t; ``` 下面的代码是DPDK中的vm_power_manager应用程序中的set_channel_status_all()函数,在自旋锁临界区更新了channel的状态和变化的channel的数量,这种保护在像DPDK这种支持多核的应用中是非常必要的。 ```c Int set_channel_status_all(const char *vm_name, enum channel_status status) { … rte_spinlock_lock(&(vm_info->config_spinlock)); mask = vm_info->channel_mask; ITERATIVE_BITMASK_CHECK_64(mask, i) { vm_info->channels[i]->status = status; num_channels_changed++; } rte_spinlock_unlock(&(vm_info->config_spinlock)); return num_channels_changed; } ``` > 摘自:《深入浅出DPDK》 — 朱河清 梁存铭 胡雪焜 在豆瓣阅读书店查看:https://read.douban.com/ebook/21808108/ 本作品由华章数媒授权豆瓣阅读全球范围内电子版制作与发行。 © 版权所有,侵权必究。
上一篇:
这是无锁队列机制吗???
下一篇:
这是读写锁吗???
0
赞
596 人读过
新浪微博
微信
腾讯微博
QQ空间
人人网
提交评论
0
条评论
More...
<>