LDD读书笔记——并发与竞态

信号量semaphore

        down_interruptible故名思义是可以被中断的(这也是为什么要检查返回值的原因),而与之对应的是down无法被中断,这个接口是一般不用的。


读写信号量rwsem( read/write semaphore )

        接口命名上与信号量类似。


completion

        completion用于“在当前线程这外初始化某个活动,然后等待该活动完成”,接口主要是:wait_for_completioncomplete/complete_all,另外“completion通常是一个单次(one-shot)设备;也就是说,它只会被使用一次后被丢弃”。


自旋锁spinlock

    自旋锁其实就是只能有两个值——锁定或解锁的锁机制,若锁被别人获得,代码将进入忙循环重复检查锁,这就是“自旋”的由来。

    要注意的是:自旋锁在忙等待过程中是不可被中断的——也正是因为此,自旋锁只适合用于临界区十分短小的情况,不过虽然看起来效率低下,实则比异步唤醒要快的多;获得自旋锁后,不可以使用可能导致当前进程进入阻塞的代码(但书说临界区内代码都必须是原子,有这个必要?),准确的说是不能以除响应中断外的任何原因放弃本地处理器,有的甚至连中断也可以不响应(但最好不要禁用中断);自旋锁仅在SMP中有效;自旋锁的两种形式:完全锁(full lock)和读写锁。

    自旋完全锁的锁接口有四个:spin_lock就是最普通的;spin_lock_irqsavespin_lock_irq都是屏蔽本地中断的,区别在于前面会记录当前的中断情况,而后者“会假设中断状态”;spin_lock_bh不屏蔽硬中断但屏蔽信号、tasklet、底半部。而解锁接口与锁接口一一对应也有四个,接口名中将lock换为unlock即可。


预防锁出错的方法

    对在使用锁的地方增加注释说明;在使用多个锁的地方,注意锁顺序。


免锁算法

    原子变量 通过atomic_t声明的int变量,初始化后的对其读写,加减,测试操作只要调用与之对应的atomic接口,则这些操作都是原子的。在实现上,由于C不能实现原子操作,故不同的低层架构有着不同的实现方法,有的是使用汇编,有的使用C加上local_irq_savelocal_irq_restore禁用中断。虽归为免锁算法,但也有将这种方法称为原子锁的。

    位操作 与原子变量类似,由专门的接口用于读写,位测试等接口保证其位操作的原子性。

    seqlock 使用的前提为:1.读操作远多于写操作;2.共享资源内不含有指针或者不会对指针进行任何读写操作。原理是在进入共享区时,系统给一个无符号整形数,进程在完成操作后,会与系统比较该数,若相同则无写操作发生,结束;若不同,则说明有写操作发生,重做。这样就可以免去锁机制了。

    RCUread-copy-update在需要修改时,先整个复制下来,然后直接修改副本,待原版无引用时,再完成替换。可以看出,类似seqlock,也是针对多读少写的情况。


PS:除了LDD,还主要参考了linux同步方法剖析一文。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值