Linux内核同步机制RT-mutex

本文详细介绍了Linux内核中rt_mutex的实现原理,特别是在PREEMPT_RT补丁后如何通过优先级继承解决优先级翻转问题,确保实时性的提升。rt_mutex使得中断处理线程化,支持抢占和休眠,使用rt_mutex和红黑树数据结构维护优先级继承链,保证高优先级任务的及时执行。此外,rt_mutex还应用于PI-futex,确保用户态线程按照优先级顺序唤醒。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Linux内核打上了PREEMPT_RT补丁之后支持完全可抢占,中断处理将线程化,线程化之后允许抢占和休眠,因此原本中断处理中使用的spinlock,实际上也将替换为使用rt_mutex。

互斥量加上了rt的前缀,主要是因为支持优先级继承,防止优先级翻转造成的高优先级任务等待时间的不确定性。优先级翻转可以通过下面这张图来理解。

图中3个进程的优先级A>B>C。假设低优先级的进程C和高优先级进程A竞争共享资源,而C先持有了lock,A只能阻塞等待C释放lock。假如A阻塞期间有更高优先级的进程B开始运行,并抢占了C,则A必须等B运行完将CPU还给C,C释放锁之后才能运行,这就不能保证高优先级的任务先获得CPU,如果抢占C的进程不光有B,还有B1、B2等,那A的运行时间将更不确定,而实时性最为关注的就是确定性。

rt_mutex通过优先级继承解决了优先级翻转的问题,说来也简单,也就是低优先级进程C在持有lock期间临时的继承了阻塞在这个lock上的最高优先级进程的优先级,保证不会被中间优先级的进程(例如上述例子的进程B)抢占,当lock被释放后最高优先级的进程得以运行。

rt_mutex的实现在内核的kernel/locking/rtmutex.c,主要涉及了下面三个数据类型:

  • 在struct rt_mutex中记录了owner和所有的waiters(进程),使用红黑树实现,称为Mutex Waiter List,优先级最高的那一个叫top waiter。

  • struct rt_mutex_waiter是用来链接rt_mutex和task_struct的数据结构,保存了waiter是哪个进程(task_struct)在等待哪个lock(rt_mutex)

  • 在大名鼎鼎的struct task_struct中同样有一个waiters列表,使用红黑树实现,称为Task PI List列表中包含此进程持有所有rt_mutex的top waiter,称作top pi waiter。

有了这三种数据类型,就能组成PI chain,也就是优先级继承链,例如:

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

这个Pi chain表示进程E在等L4(rt_mutex)的持有者D释放锁,而D又在等L3的持有者释放锁,以此类推,到A为终点,A是owner,不是waiter。这个Pi chain用刚提到的三个数据类型表示就变成下面这个样子。

假如进程E有最高优先级,当E加入到这个继承链时,将加入到L4的waiters中,并成为top waiter,由于L4的owner是D,D将更新waiters,E成为D进程的top pi waiter,为了避免发生优先级翻转,持有L4的D临时提升优先级与E相等。由于D的优先级提升,并且D是L3的waiter,这个优先级继承的动作将沿着继承链传播,直到最后一个进程A。这就是RT-mutex优先级继承的核心机制。

由于一个rt_mutex可以有多个waiter,同一个进程虽然只能是一个rt_mutex的waiter,但是可以持有多个rt_mutex,PI chain还有可以不少变化。

除了在完全可抢占时代替spinlock,rt_mutex还用在PI-futex,当用户态线程使用pthread_cond_broadcast时所有被唤醒的task也使用了rt_mutex保证所有线程按照优先级顺序依次唤醒。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值