标签:bar 性方面 版本 real ike ldl static 方便 and
关键词:RT、preempt_count、RT patch。
除了CFS调度器之外,还包括重要的实时调度器,有两种RR和FIFO调度策略。本章只是一个简单的介绍。
更详细的介绍参考《Linux进程管理 (9)实时调度类分析,以及FIFO和RR对比实验》。
同时为了提高Linux的实时性,Linux社区还维护了realtime相关的补丁。这些补丁的介绍在《Linux实时补丁及其分析》。
如果Linux内核不支持抢占,那么进程要么主动要求调度,如schedule()或者cond_resched();要么在系统调用、异常处理和中断处理完成返回用户空间前夕。
在支持可抢占内核中,如果唤醒动作发生在系统调用或者异常处理上下文中,在下一次调用preempt_enable()是会检查是否需要抢占调度;
中断处理返回前夕会检查是否要抢占当前进程,注意这里是中断返回而不是不支持抢占情况的用户空间返回。
struct thread_info成员preempt_count计数表示内核是否可以被完全抢占,当preempt_count为0时,表示内核可以被安全抢占;大于0时则禁止抢占。
preempt_count是32bit,低8位用于抢占计数PREEMPT_ACTIVE表示一个很大的抢占计数,通常用于表示抢占调度。
内核提供preempt_disable()来关闭抢占,preempt_count会加1。preempt_enable()函数打开抢占,preempt_count减1后判断是否为0,并检查thread_info的TIF_NEED_RESCHED标志位,如果为0,则用schedule() 完成调度抢占。
#define preempt_disable() do { preempt_count_inc(); \----------------------------------------对当前current_thread_info()->preempt_count加1 barrier(); } while (0) #define preempt_count_inc() preempt_count_add(1) #define preempt_count_add(val) __preempt_count_add(val) static __always_inline void __preempt_count_add(int val) { *preempt_count_ptr() += val; }
#define preempt_enable() do { barrier(); if (unlikely(preempt_count_dec_and_test())) \-----------------prermpt_count减1后为0,且TIF_NEED_RESCHED被置位,则进行schedule()调度抢占。 __preempt_schedule(); } while (0) static __always_inline bool __preempt_count_dec_and_test(void) { return !--*preempt_count_ptr() && tif_need_resched();---------对当前preempt_count减1并判断是否为0,如果为0则检查TIF_NEED_RESCHED } static __always_inline int *preempt_count_ptr(void) { return ¤t_thread_info()->preempt_count; } #define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED)-----测试TIF_NEED_RESCHED是否置位 #define test_thread_flag(flag) \ test_ti_thread_flag(current_thread_info(), flag) #define __preempt_schedule() preempt_schedule() asmlinkage __visible void __sched notrace preempt_schedule(void) { if (likely(!preemptible()))-----------------------------------判断当前preempt_count是否为0,并且irq没有被禁止。 return; preempt_schedule_common();------------------------------------__schedule()调度抢占。 }
# define preemptible() (preempt_count() == 0 && !irqs_disabled())
static void __sched notrace preempt_schedule_common(void) { do { __preempt_count_add(PREEMPT_ACTIVE); __schedule(); __preempt_count_sub(PREEMPT_ACTIVE); /* * Check again in case we missed a preemption opportunity * between schedule and now. */ barrier(); } while (need_resched()); }
Linux在提高实时性方面取得一系列进展,具体如下:
主要功能 | 内核版本 | 说明 |
Preemption suport | 2.5 | |
PI Mutexes | N/A | PI即Priority Inheritance,优先级继承的互斥体 |
HR Timer | 2.6.24 | 高精度定时器 |
Preemptive RCU | 2.6.25 | 可抢占RCU |
IRQ Threads | 2.6.30 | 中断线程化 |
Forced IRQ Threads | 2.6.39 | 强制中断线程化 |
Deadline scheduler | 3.14 | Deadline调度器 |
Full Realtime Preemption support | rt-patches | rt.wiki.kernel.org |
内核提供了一些接口、工具,使我们得以一窥调度延迟。常用的有个ftrace的调度器preemptirqoff、等,以及工具latencytop、cyclictest等。
preemptirqsoff可以跟踪关闭中断并禁止进程抢占代码的延时,同时记录关闭的最大时长。
latencytop在内核上下文切换时记录被切换进程的内核栈,然后通过匹配内核栈函数来判断导致上下文切换的原因。
方便判断系统出现哪方面的延迟,还能查看某个进程或者线程的延迟情况。
标签:bar 性方面 版本 real ike ldl static 方便 and
原文地址:https://www.cnblogs.com/arnoldlu/p/8470034.html