请选择 进入手机版 | 继续访问电脑版

雨林木风

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8|回复: 0

Linuxkernel同步机制及原子操作自旋锁信号量和互斥锁

[复制链接]

1万

主题

1万

帖子

3万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
32176
发表于 2021-2-17 22:17:10 | 显示全部楼层 |阅读模式
  正在新颖操作体例里,同临时间也许有众个内核履行流正在履行,于是内核原本像众经过众线程编程相同也需求少少同步机制来同步各履行单位对共享数据的拜望,加倍是正在众打点器体例上,更需求少少同步机制来同步分歧打点器上的履行单位对共享的数据的拜望。正在主流的
  原子操作的观点来历于物理观点中的原子界说,指履行遣散前不成支解(即不成打断)的操作,是最小的履行单元。
  原子操作与硬件架构强闭系,其API全部的界说均位于对应arch目次下的include/asm/atomic.h文献中,通过汇编言语杀青,内核源码根目次下的include/asm-generic/atomic.h则空洞封装了API,该API结果分配的杀青来自于arch目次下对应的代码。
  原子操作厉重用于杀青资源计数,很众援用计数(refcnt)即是通过原子操作杀青,比方TCP/IP订交栈的IP碎片中,structipq中的refcnt字段,类型即为atomic_t。

  原子操作的原子性依赖于ldrex与strex杀青,ldrex读取数据时会举行私有记号,防卫其他内核旅途拜望,直至移用strex实行写入后根除记号。自然strex也不行写入被其余内核旅途私有的内存,假使写入曲折则轮回至告成写入。

  自旋锁是如此一种同步机制:若自旋锁已被其余履行者维持,移用者就会原地轮回守候并反省该锁的持有者是否依然开释锁(即进入自旋形态),若开释则移用者初阶持有该锁。自旋锁持有功夫不成被抢占。

  从界说动身,spinlock基础的杀青依赖于全部架构杀青中slock这个变量,因为spin_lock是公共locking机制的根蒂,咱们看一看它的杀青。
  spin_lock用于遏制正在分歧CPU上的履行单位对共享资源的同时拜望以及分歧经过上下文彼此抢占导致的对共享资源的非同步拜望,而停滞失效(spin_lock_irq)和软停滞失效(spin_lock_bh)却是为了遏制正在统一CPU上软停滞或停滞对共享资源的非同步拜望。
  倘使被袒护的共享资源只正在经过上下文拜望和软停滞上下文拜望,那么当正在经过上下文拜望共享资源时,也许被软停滞打断,从而也许进入软停滞上下文来对被袒护的共享资源拜望,于是看待这种状况,对共享资源的拜望最好应用spin_lock_bh和spin_unlock_bh来袒护。
  倘使被袒护的共享资源只正在经过上下文和tasklet或timer上下文拜望,那么应当应用与上面状况肖似,由于tasklet和timer是用软停滞杀青的。
  倘使被袒护的共享资源只正在两个或众个tasklet或timer上下文拜望,那么对共享资源的拜望仅需求用spin_lock和spin_unlock来袒护,不必应用_bh版本,由于当tasklet或timer运转时,不也许有其他tasklet或timer正在现时CPU上运转。倘使被袒护的共享资源只正在一个软停滞(tasklet和timer除外)上下文拜望,那么这个共享资源需求用spin_lock和spin_unlock来袒护,由于同样的软停滞可能同时正在分歧的CPU上运转。
  倘使被袒护的共享资源正在软停滞(囊括tasklet和timer)或经过上下文和硬停滞上下文拜望,那么正在软停滞或经过上下文拜望功夫,也许被硬停滞打断,从而进入硬停滞上下文对共享资源举行拜望,于是,正在经过或软停滞上下文需求应用spin_lock_irq和spin_unlock_irq来袒护对共享资源的拜望。
  Linux内核的信号量正在观点和道理上与用户态的SystemV的IPC机制信号量是相同的,然则它不也许正在内核以外应用,于是它与SystemV的IPC机制信号量十足分歧。
  信号量是如此一种同步机制:信号量正在创修时设立一个初始值count,用于流露现时可用的资源数。一个义务要思拜望共享资源,最初务必获得信号量,获守信号量的操举动count-1,若现时count为负数,解释无法获取信号量,该义务务必挂起正在该信号量的守候队伍守候;若现时count为非负数,流露可获取信号量,因此可马上拜望被该信号量袒护的共享资源。当义务拜望完被信号量袒护的共享资源后,务必开释信号量,开释信号量通过把count+1杀青,倘使count为非正数,解释有义务守候,它也叫醒悉数守候该信号量的义务。

  可能呈现,信号量是基于spinlock杀青的,对其封装以知足高级的效用,比方整体共享资源的摆设,并通过守候队伍较为天真的调剂。信号量与接下来要讲的mutex都兴办正在自旋锁杀青的履行同步上。

  down用于移用者获取信号量,若count大于0,讲明资源可用,将其减一即可。


  up用于移用者开释信号量,若waitlist为空,讲明无守候义务,count+1,该信号量可用。


  Linux内核互斥锁黑白屡屡用的同步机制,互斥锁是如此一种同步机制:正在互斥锁中同时只可有一个义务可能拜望该锁袒护的共享资源,且开释锁和获取锁的移用方务必划一。于是正在互斥锁中,除了对锁自己举行同步,对换用方(或称持有者)务必也举行同步。当互斥锁无法获取时,task会插手守候队伍,直至可获取锁为止。

  互斥锁从布局上看与信号量相称相似,但将蓝本的int类型的count计数,改成了atomic_long_t的owner以便同步,保障开释者与持有者划一。


  因为mutex杀青的全部措施相当庞大,这里选讲较量中心简便的两块。Mutex相闭守候队伍的打点较量庞大,有意思阅读闭系内核竹帛。

  当且仅当lock现时的owner没有改变时(没有其他mutex争先具有该锁),此时获取锁,返回NULL,owner为currflags,owner自己对应task指针。若该锁已被占用,owner和现时task不结婚,返回owner对应指针。

  当unlock时,不研商守候队伍的影响,则与上述相似,当且仅当之前持有锁的owner可能解锁,解锁时原本应将lock的owner置为初始0,然则这里保存了mutex的flag以便后续操作。
  *这里的owner实践上是task_struct的指针,也即是所在,因为task_struct的所在是L1_cache对齐的,于是实践上指针所在后三位为0,于是linux内核操纵这三个比特位用于设立mutex的象征位,不影响指针所在的流露也更高效操纵了冗余的比特位。
  最初的互斥锁仅援助睡眠守候,然而源委漫长工夫的改善,目前的互斥锁依然可能援助自旋守候,通过MCS锁机制杀青。正在内核中可能采选摆设以援助,CONFIG_MUTEX_SPIN_ON_OWNER。

  如上是4.9内核中mutex中常用有用的字段,目前最常用的算法是OSQ算法。自旋守候机制的中心道理是当呈现持有者正正在临界区履行而且没有其他优先级高的经过要被调剂(need_resched)时,那么mutex现时所正在经过以为该持有者很疾会脱节临界区并开释锁,此时mutex采选自旋守候,短工夫的自旋守候昭着比睡眠-叫醒开销小少少。
  正在杀青上MCS保障了同临时间只要一个经过自旋守候持有者开释锁。MCS的杀青较为庞大,全部可参考少少内核竹帛。MCS保障了不会存正在众个cpu争用锁的状况,从而避免了众个CPU的cacheline波动从而下降体例职能的题目。
  源委改善后,mutex的职能有了相当大的提升,相对信号量的杀青要高效得众。于是咱们尽量选用mutex。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

|appname
快速回复 返回顶部 返回列表