美文网首页
5.内核同步

5.内核同步

作者: 大雄good | 来源:发表于2016-12-08 15:07 被阅读0次

    内核同步

    在使用共享内存的应用程序中,程序员必须留意保护共享资源,防止对共享资源的并发访问,内核也不例外。如果多个执行线程同时访问和操作数据,就有可能发生各线程之间相互覆盖共享数据的情况,造成被访问的数据处于不一致状态。

    1.临界区和竞争条件

    临界区就是访问和操作共享数据的代码段。多个执行线程并发访问同一个资源是不安全的,因此通常对临界区采用原子操作(顾名思义,这些操作看作一个原子,不可分的单元)。若两个执行线程处于同一个临界区同时执行,这是一个bug,称这种情况为竞争条件。避免并发和防止竞争条件称为同步(synchronization)

    2.造成并发执行的原因

    内核中造成并发执行的原因有:

    • 中断,中断可能随时打断当前执行的代码
    • 软中断和tasklet
    • 内核抢占,内核中的任务可能被另一个任务抢占
    • 睡眠以及与用户空间的同步,内核执行的进程可能睡眠,就会唤醒调度程序,从而导致调度一个新的用户进程执行
    • 对此多处理,多个处理器同时执行代码

    3.死锁

    死锁需要四个必要条件:

    • 互斥条件:一个资源每次只能被一个进程使用
    • 请求与保持条件:一个进程因请求资源而阻塞时,不释放已获得资源
    • 不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺
    • 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系

    4.内核同步方法

    Linux内核提供了一组相当完备的同步方法。

    原子操作

    内核提供了两组原子操作接口——一组针对整数进行操作,另一组针对单独的位进行操作。

    自旋锁

    Linux内核中最常见的锁是自旋锁自旋锁只能被一个可执行线程持有。若一个执行线程试图获得一个被占用的自旋锁,那么该线程就会一直忙循环——旋转——等待锁重新可用。

    用现实生活例子解释,你去上厕所,厕所只有一个坑,先去的那人把门锁了,你只有抽根烟,再去看看出来没,没出来再去抽根烟,在回来看看...只有持锁的人才能开门,所以自旋锁不适合长时间占用临界区的执行线程。

    Linux中自旋锁接口定义在<linux/spinlock.h>中,基本形式如下:

    DEFINE_SPINLOCK(mr_lock);
    spin_lock(&mr_lock);
    /*临界区*/
    spin_unlock(&mr_lock);
    

    对于读写操作,还存在读-写自旋锁

    • 一个或多个读任务可以并发持有读者锁
    • 写的锁最多只能被一个写任务持有,而且此时不能有并发读操作

    信号量

    Linux中的信号量是一种睡眠锁。如果一个任务试图获得一个不可用的信号量时,信号量会将其推进一个等待队列,然后让其睡眠。此时处理器能重获自由,从而执行其他代码。

    同样是上厕所,这个厕所升级了,具有一个记录和通知功能,当发现厕所坑被占用之后,到来的人就在册子末尾添加自己的电话,你就可以继续去抽烟泡妞。等蹲坑那哥们一出来,就挑选册子上第一个电话号码,打电话通知你,兄弟来上厕所。

    计数信号量是高级版信号量,就是说允许多个执行线程(多个但是有上限)同时访问临界区。通过PV操作执行计数器的加减操作。

    继续上厕所,厕所扩容了,不止一个坑!!!因此这里就有一个计数器,最大值就是坑数,来一个人就减一,走一个人就加一。计数器为0时,嘿嘿,小伙,再夹一会吧,有坑,哥会打电话给你的。

    互斥体(mutex)

    互斥体和信号量类似,但是互斥体的上锁者必须负责给其解锁,因此互斥体不适合内核同用户空间复杂的同步场景,更多用于同一上下文的上锁和解锁。

    小结

    同步是是Linux以及多线程编程等场景下非常重要的内容,需要进一步了解同步的知识,需要动手实验一下。

    相关文章

      网友评论

          本文标题:5.内核同步

          本文链接:https://www.haomeiwen.com/subject/pirsmttx.html