Linux优化-Preempt RT关键点
 2016.04.02    |      Linux MMC子系统    |     AilsonJack    |     暂无评论    |     3733 views
By: Ailson Jack
Date: 2016-04-02
个人博客: http://www.only2fire.com/
<p style="text-indent: 2em;">最近看了看preempt-rt的一些材料,觉得网友的总结还是可以,这里就分享出来供大家学习之用,总结的几个preempt-rt关键点如下:</p><p style="text-align:center"><img src="/uploads/AilsonJack/2018.08.25/1535194186812965.jpg" onclick="preview_image(&#39;/uploads/AilsonJack/2018.08.25/1535194186812965.jpg&#39;)"/></p><p class="artical_littlestyle1">1、preemptible critical sections</p><p style="text-indent: 2em;"><span style="background-color: rgb(118, 146, 60);">1.1</span> 用支持PI的rt_mutex代替传统的禁用抢占的spin_lock,定义了新的数据类型:spin_lock_t。凡是使用spin_lock_t做参数的spin_lock函数行为有可能引起调度,不会禁用抢占。如果,希望使用传统的spin_lock,则需要使用raw_spin_lock_t类型作为参数。<br/></p><p style="text-indent: 2em;"><span style="background-color: rgb(118, 146, 60);">1.2</span> 同时,要注意per CPU变量的问题,以前用spin_lock保护的per CPU变量,现在会出现问题,即在现在的spin_lock中进程照样会睡眠,然后调度到别的CPU上。因此,引入了一个新的宏来定义一种可以锁住的per CPU变量。DEFINE_PER_CPU_LOCKED,就是这样的宏,通过get_cpu_var_locked来操作per CPU变量。不过,以前使用get_cpu/put_cpu保护的per CPU变量不受影响。<br/></p><p style="text-indent: 2em;"><span style="background-color: rgb(118, 146, 60);">1.3</span> 还有一种情况,就是在显示的改变的进程状态之后,调用spin_lock,参考下面的代码序列:<br/><span style="color: rgb(0, 112, 192);">spin_lock(&amp;mylock1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;current-&gt;state = TASK_UNINTERRUPTIBLE;<br/>&nbsp;&nbsp;&nbsp;&nbsp;spin_lock(&amp;mylock2); // [*]<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;blah();<br/>&nbsp;&nbsp;&nbsp;&nbsp;spin_unlock(&amp;mylock2);<br/>spin_unlock(&amp;mylock1);</span><br/></p><p style="text-indent: 2em;">在锁住mylock2之前,进程被设置为TASK_UNINTERRUPTIBLE状态,但是现在spin_lock的行为与mutex一样,所以当获得mylock2的时候,进程有可能被设置为TASK_RUNNING状态,则与前面的逻辑相矛盾。所以,引入了TASK_MUTEX_RUNNING状态。这样,代码会选择将进程状态设置为以前的状态还是TASK_RUNNING。<br/></p><p class="artical_littlestyle2">2、preemptible interrupt handlers</p><p style="text-indent: 2em;">在preempt-rt环境下,中断处理程序是运行在进程上下文中的,这与传统情况大相径庭,所以处理上有很多需要注意的地方。大概的过程是,redirect_hardirq唤醒某个中断处理程序(实际上是一个进程),然后交由do_irqd在进程上下文中执行。<br/></p><p style="text-indent: 2em;">如果,希望某个中断处理程序继续运行在中断上下文中,需要将该中断处理程序设置为SA_NODELAY。在这种情况下,任何于进程上下文的互斥都要使用raw_spin_lock_t来处理。</p><p class="artical_littlestyle3">3、preemptible “interrupt disable” code sequence</p><p style="text-indent: 2em;">在preempt-rt环境下,spin_lock_irqsave并不会禁用中断和抢占,而且local_irq_save也不会禁用中断,只会禁用抢占。必须与SA_NODELAY类型中断打交道的代码不能使用local_irq_save,因为它不会真正禁用中断,此时,必须使用raw_local_irq_save。</p><p class="artical_littlestyle4">4、priority inheritance for in-kernel spinlocks and semaphore</p><p style="text-indent: 2em;">对于preempt-rt中的spinlock来说,实现都是支持PI的rt_mutex,即能够解决优先级翻转问题。优先级翻转是实时系统中比较严重的问题,具体成因是:<br/></p><p style="text-indent: 2em;">进程A,B,C,其中优先级A&gt;B&gt;C。C持有锁S,A需要S,则A睡眠在S上,但是B抢占C,则A只有等到B运行结束,C释放S后才能继续运行。这样就造成了优先级翻转问题。<br/></p><p style="text-indent: 2em;">解决办法是,在A尝试获得S的时候,判断持有S的进程与A的优先级,如果A的优先级更高,则提升C的优先级与A一样高。如果,C还依赖于某一个锁,这样循环下去,则需要循环提升持有锁的进程的优先级。当C释放S时,恢复C的优先级。<br/></p><p style="text-indent: 2em;">一旦,C释放S,则A尝试获得S,这时S在pending状态,这时,更高优先级的进程可以尝试抢占A,否则A将彻底获得S。这种优化通过在spin_lock_t中加入task_struct指针实现,指针的低两位作为锁的状态位。在pending向held状态转化过程中,是更高优先级进程“steal”锁的时机。在这个例子里面,A就是S的top waiter。<br/></p><p style="text-indent: 2em;">针对于读写锁,由于依赖情况比较负责,preempt-rt做了简化,即只容许一个进程在一个时间持有一个读锁。<br/></p><p style="text-indent: 2em;">但是,这里面也有例外,某些用于同步的semaphore,不能执行PI,因为,不知道哪个进程持有这个semaphore,所以无法比较优先级。这种情况需要使用compat_semaphore或者compat_rw_semaphore代替。</p><p class="artical_littlestyle1">5、deferred operations</p><p style="text-indent: 2em;">由于spin_lock可以睡眠,因此在禁用抢占期间代用spin_lock是非法的。在这种情况下preempt-rt提供了一些解决办法:<br/></p><p style="text-indent: 2em;">put_task_struct_delayed排队put_task_struct稍后执行;<br/></p><p style="text-indent: 2em;">mmdrop_delayed排队mm_drop稍后执行;<br/></p><p style="text-indent: 2em;">TIF_NEED_RESCHED_DELAYED执行重调度,在进程准备返回到用户空间时,或者直到下一个preempt_check_resched_delayed。</p><p class="artical_littlestyle2">6、latency-reduction measures</p><p style="text-indent: 2em;">preempt-rt中还有一些改变的主要目的是减少调度或中断延迟。<br/></p><p style="text-indent: 2em;">第一个例子是x86的MMX/SSE硬件。这些硬件在内核中处理时禁用抢占,需要等待前面的指令完成,但是一些指令执行时间很长,preempt-rt做了改变。<br/></p><p style="text-indent: 2em;">第二个例子是使用slab分配器分配per CPU变量。<br/></p>
欢迎关注博主的公众号呀,精彩内容随时掌握:
热情邀请仔细浏览下博客中的广告,万一有对自己有用或感兴趣的呢。◕ᴗ◕。。
如果这篇文章对你有帮助,记得点赞和关注博主就行了^_^,当然了能够赞赏博主,那就非常感谢啦!
注: 转载请注明出处,谢谢!^_^
转载请注明来源: 本文链接:  By: AilsonJack
Linux优化-Preempt RT关键点  |  说好一起走
暂无评论,要不要来个沙发
发表评论

 
Copyright © 2015~2023  说好一起走   保留所有权利   |  百度统计  蜀ICP备15004292号