linux 内核的rt_mutex (realtime互斥体)

linux 内核有实时互斥体(锁),名为rt_mutex即realtime mutex。说到realtime一定离不开priority(优先级)。所谓实时,就是根据优先级的不同对任务作出不同速度的响应。rt_mutex也就是依据任务(task,process)的priority进行排队的锁,同时使用PI(priority Inheritance,优先级继承)算法解决proirty inversion(优先级逆转)的问题。 

这里有三个角色:rt_mutex,rt_mutex_waiter,以及task_struct。(pi算法与进程结构偶合在一起)

rt_mutex:实时锁,使用优先级排队,使用优先级继承算法解决优先级逆转问题,与task_struct强偶合。

task_struct:要求锁的任务,rt_mutex用其指针作为上锁状态。

rt_mutex_waiter:任务阻塞等待锁,即任务与锁的关联,代表任务对锁的一次需求。

rt_mutex和task_struct都有一个waiter有序队列,并且都实现为rb树,并以优先级prio进行排序。rt_mutex_waiter->tree_entry入队到rt_mutex(锁)的waiter队列,即rt_mutex->waiters。而rt_mutex_waiter->pi_tree_entry入队到task_struct(任务)的waiter队列,即task_struct->pi_waiters。

rt_mutex->waiters:用于阻塞等待排队,与pi chain无关。

task_struct->pi_waiters:并非用于排队,而是作为一个最小值计算器,为task_struct计算可继承的最小prio(最高),并且提供一个是否为空的判断属性。它收集了task持有的所有rt_mutex的leftmost_waiter,即每当一个task在一个rt_mutex上了锁,这个rt_mutex的waiters中prio最小(最高)的waiter将被入队到task_struct->pi_waiters。与pi chain无关。

rt_mutex_waiter->prio:rt_mutex->waiters和task_struct->pi_waiters两个队列都使用这个值进行排序。一个在pi chain上阻塞的任务,当优先级被boost后,同样会反映在waiter结构的prio上。

 

pi chain:从一个任务的task_struct->pi_block_on开始,依次进行rt_mutex = rt_mutex_waiter->lock,task_struct = rt_mutex->owner,rt_mutex_waiter = task_struct->pi_block_on访问遍历。这个链并非我们通过指的用链表结构进行链接的链表。而是 task -> waiter -> lock -> ... 的chain。虽然rt_mutex->waiters 和 task_struct->pi_waiters 同为队列(由rbtree实现),但是跟pi chain无关,pi chain walk路径不通过这两个队列。

以内核的设计文档rt-mutex-design.txt举例,有pi chain如下

Example:

   Process:  A, B, C, D, E
   Mutexes:  L1, L2, L3, L4

   A owns: L1
           B blocked on L1
           B owns L2
                  C blocked on L2
                  C owns L3
                         D blocked on L3
                         D owns L4
                                E blocked on L4

The chain would be:

   E->L4->D->L3->C->L2->B->L1->A

在上面的例子中,A为最终的阻塞源,它继承了阻塞链上所有其它任务的优先级。图左则的任务被右则的任务阻塞,图右则的任务持有锁并继承图左则的任务的优先级。当一个任务被一个锁阻塞,并且这个锁在图上。以任务E为例,当E加入到pi chain后,就会从图的左则向图的右则进行pi chain walk,直到到达任务A,在walk所经节点,都会将优先级作最优继承。通常地pi chain由图最右则的A释放锁,一路唤醒pi chain上阻塞的任务,而消减pi chain。A首先离开pi chain,由于继承了优先级,必须马上恢复原有的优先级,但是并不需要进行pi chain walk,因为它是继承者不是继承源(没有pi_block_on),不影响其它继承者(pi chain上的任务)的继承。 但是如C,超时不阻塞了,要离开pi chain,因为它不但是继承者还是继承源(pi_block_on -> B),所以C必须对B进行pi chain walk。

下面是进行walk chain的调用拓扑,rt_mutex_adjust_prio_chain执行pi chain walk。

 

 

pi算法解决优先级逆转问题。

高(high)优先级任务由于等待低(low)优先级任务拥有的锁,在这过程中低优先级被其它优先级(界于高低之间的中级medium)的任务无限抢占,从而有机会释放锁,导致高优先级的任务无限等待。

下面设两轴,水平轴为时间,纵轴为优先级。

当一个high prio任务进来,抢占一个low prio任务后却发现有资源要同步又阻塞了,而这个同步的资源low prio任务正在使用,那么必须等待low prio任务释放掉同步的资源,high prio任务才能再次运行。但是有一种坏的情况是,low prio任务被medium prio任务抢占,不能及时释放同步的资源,使用high prio任务阻塞时间增加。

这还不算最坏的,最坏的是low prio任务被不定数目或不定回目的medium prio任务无限地进行抢占,最后导致high prio任务无限地被阻塞。

解决的方法就是,当high prio任务阻塞在一个同步资源时,将正在使用同步资源的任务临时提升 (boost)跟自己一样的优先级,赶紧释放资源,好让(方便)high prio任务通过。

 

rt_mutex->waiters 和 task_struct->pi_waiters 如何参与pi算法。

前面已经谈及的pi chain,也是pi算法的一部分。而pi算法的另一部分就是如何选出最高的优先级进行继承。这是通过rt_mutex->waiters和task_struct->pi_waiters队列来实现的。每当一个任务持有一个rt_mutex时,就会从rt_mutex->waiters中选出排在首位的waiter纳入到自己的task_struct->pi_waiters队列,这个同样是一个排序队列。这个队列代表着任务持有哪些rt_mutex,并且以及阻塞在这些rt_mutex的最高优先级(的任务)。这个队列将这些优先级进行排序选出最高的优先级进行继承。

一个对rt_mutex的lock或者unlock都可能会引发rt_mutex->waiters队列的入队和出队,从而改变了rt_mutex->waiters的排序,继而改变了task_struct->pi_waiters队列的成员,必须重新排序,选择新的优先级来继承。当pi chain上的一个任务的优先级继承受影响后,就必须要反映在它所阻塞的rt_mutex的waiters队列上,并按pi chain阻塞的方向传递变化。

任务 P 持有两个锁 L1 和 L2。A,B,C 阻塞在 L1;而 C,D,F 阻塞在 L2。 B 和 F 分别是 L1 和 L2 的 leftmost waiter,以最好的优先级 1 和 0,被任务 P 选中放在自己的 pi_waiters 队列。排序后,F 的优先级最高,作为继承的优先级。

当一个优先级更高的任务 X 需要阻塞在锁 L1 时,必然引发锁 L1的leftmost waiter改变,这时就要通知 P 选择 X 代替 B,重新对比 X 和 F 的优先级,选最高的优先级来继承。如果任务 P 还阻塞等待一个锁 L3 ,那么就必须进行 pi chain walk,通知优先级继承变更。

一个阻塞任务从其task_struct->pi_block_on开始进行 pi chain walk 通知优先级继承变更。

一个任务释放锁,从其task_struct->pi_waiters队列找出锁对应的任务进行唤醒。

转载于:https://www.cnblogs.com/bbqzsl/p/6745460.html

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值