编辑
2025-03-30
工作知识
0
请注意,本文编写于 68 天前,最后修改于 68 天前,其中某些信息可能已经过时。

目录

一、简单优先级调度
二、优先级调度
三、最早截止时间优先调度
四、恒定带宽调度
五、基于SMP的调度器扩展
六、其他调度器
七、系统默认调度器

RTEMS支持多种调度算法,默认情况下是基于优先级的调度器,为了了解这些调度器算法,本文列出RTEMS支持的调度器种类,方便后续逐一进行调度器的测试研究

一、简单优先级调度

Simple Priority Scheduler是基于优先级调度的一种简化算法,其初始化如下:

#define CONFIGURE_SCHEDULER_TABLE_ENTRIES \ RTEMS_SCHEDULER_TABLE_SIMPLE( dflt, CONFIGURE_SCHEDULER_NAME ) #define SCHEDULER_SIMPLE_ENTRY_POINTS \ { \ _Scheduler_simple_Initialize, /* initialize entry point */ \ _Scheduler_simple_Schedule, /* schedule entry point */ \ _Scheduler_simple_Yield, /* yield entry point */ \ _Scheduler_simple_Block, /* block entry point */ \ _Scheduler_simple_Unblock, /* unblock entry point */ \ _Scheduler_simple_Update_priority, /* update priority entry point */ \ _Scheduler_default_Map_priority, /* map priority entry point */ \ _Scheduler_default_Unmap_priority, /* unmap priority entry point */ \ SCHEDULER_DEFAULT_SMP_OPERATIONS \ _Scheduler_default_Node_initialize, /* node initialize entry point */ \ _Scheduler_default_Node_destroy, /* node destroy entry point */ \ _Scheduler_default_Release_job, /* new period of task */ \ _Scheduler_default_Cancel_job, /* cancel period of task */ \ _Scheduler_default_Start_idle /* start idle entry point */ \ SCHEDULER_DEFAULT_SET_AFFINITY_OPERATION \ }

二、优先级调度

Priority Scheduler是默认的基于优先级的调度器,其初始化如下

#define RTEMS_SCHEDULER_TABLE_PRIORITY( name, obj_name ) \ { \ &SCHEDULER_PRIORITY_CONTEXT_NAME( name ).Base.Base, \ SCHEDULER_PRIORITY_ENTRY_POINTS, \ RTEMS_ARRAY_SIZE( \ SCHEDULER_PRIORITY_CONTEXT_NAME( name ).Ready \ ) - 1, \ ( obj_name ) \ SCHEDULER_CONTROL_IS_NON_PREEMPT_MODE_SUPPORTED( true ) \ } #define SCHEDULER_PRIORITY_ENTRY_POINTS \ { \ _Scheduler_priority_Initialize, /* initialize entry point */ \ _Scheduler_priority_Schedule, /* schedule entry point */ \ _Scheduler_priority_Yield, /* yield entry point */ \ _Scheduler_priority_Block, /* block entry point */ \ _Scheduler_priority_Unblock, /* unblock entry point */ \ _Scheduler_priority_Update_priority, /* update priority entry point */ \ _Scheduler_default_Map_priority, /* map priority entry point */ \ _Scheduler_default_Unmap_priority, /* unmap priority entry point */ \ SCHEDULER_DEFAULT_SMP_OPERATIONS \ _Scheduler_priority_Node_initialize, /* node initialize entry point */ \ _Scheduler_default_Node_destroy, /* node destroy entry point */ \ _Scheduler_default_Release_job, /* new period of task */ \ _Scheduler_default_Cancel_job, /* cancel period of task */ \ _Scheduler_default_Start_idle /* start idle entry point */ \ SCHEDULER_DEFAULT_SET_AFFINITY_OPERATION \ }

三、最早截止时间优先调度

Earliest Deadline First调度按照任务的截止时间来确定任务优先级,其初始化如下

#define RTEMS_SCHEDULER_TABLE_EDF( name, obj_name ) \ { \ &SCHEDULER_EDF_CONTEXT_NAME( name ).Base, \ SCHEDULER_EDF_ENTRY_POINTS, \ SCHEDULER_EDF_MAXIMUM_PRIORITY, \ ( obj_name ) \ SCHEDULER_CONTROL_IS_NON_PREEMPT_MODE_SUPPORTED( true ) \ } #define SCHEDULER_EDF_ENTRY_POINTS \ { \ _Scheduler_EDF_Initialize, /* initialize entry point */ \ _Scheduler_EDF_Schedule, /* schedule entry point */ \ _Scheduler_EDF_Yield, /* yield entry point */ \ _Scheduler_EDF_Block, /* block entry point */ \ _Scheduler_EDF_Unblock, /* unblock entry point */ \ _Scheduler_EDF_Update_priority, /* update priority entry point */ \ _Scheduler_EDF_Map_priority, /* map priority entry point */ \ _Scheduler_EDF_Unmap_priority, /* unmap priority entry point */ \ SCHEDULER_DEFAULT_SMP_OPERATIONS \ _Scheduler_EDF_Node_initialize, /* node initialize entry point */ \ _Scheduler_default_Node_destroy, /* node destroy entry point */ \ _Scheduler_EDF_Release_job, /* new period of task */ \ _Scheduler_EDF_Cancel_job, /* cancel period of task */ \ _Scheduler_default_Start_idle /* start idle entry point */ \ SCHEDULER_DEFAULT_SET_AFFINITY_OPERATION \ }

四、恒定带宽调度

Constant Bandwidth Server调度是基于EDF的扩展,默认情况下,给任务分配固定的带宽(预算),然后再通过截止时间进行调度

#define RTEMS_SCHEDULER_TABLE_CBS( name, obj_name ) \ { \ &SCHEDULER_CBS_CONTEXT_NAME( name ).Base, \ SCHEDULER_CBS_ENTRY_POINTS, \ SCHEDULER_CBS_MAXIMUM_PRIORITY, \ ( obj_name ) \ SCHEDULER_CONTROL_IS_NON_PREEMPT_MODE_SUPPORTED( true ) \ } #define SCHEDULER_CBS_ENTRY_POINTS \ { \ _Scheduler_EDF_Initialize, /* initialize entry point */ \ _Scheduler_EDF_Schedule, /* schedule entry point */ \ _Scheduler_EDF_Yield, /* yield entry point */ \ _Scheduler_EDF_Block, /* block entry point */ \ _Scheduler_CBS_Unblock, /* unblock entry point */ \ _Scheduler_EDF_Update_priority, /* update priority entry point */ \ _Scheduler_EDF_Map_priority, /* map priority entry point */ \ _Scheduler_EDF_Unmap_priority, /* unmap priority entry point */ \ SCHEDULER_DEFAULT_SMP_OPERATIONS \ _Scheduler_CBS_Node_initialize, /* node initialize entry point */ \ _Scheduler_default_Node_destroy, /* node destroy entry point */ \ _Scheduler_CBS_Release_job, /* new period of task */ \ _Scheduler_CBS_Cancel_job, /* cancel period of task */ \ _Scheduler_default_Start_idle /* start idle entry point */ \ SCHEDULER_DEFAULT_SET_AFFINITY_OPERATION \ }

五、基于SMP的调度器扩展

为了支持SMP,简单优先级,优先级,EDF都做了SMP的扩展支持,如下

#define RTEMS_SCHEDULER_TABLE_SIMPLE_SMP( name, obj_name ) \ { \ &SCHEDULER_SIMPLE_SMP_CONTEXT_NAME( name ).Base.Base, \ SCHEDULER_SIMPLE_SMP_ENTRY_POINTS, \ SCHEDULER_SIMPLE_SMP_MAXIMUM_PRIORITY, \ ( obj_name ) \ SCHEDULER_CONTROL_IS_NON_PREEMPT_MODE_SUPPORTED( false ) \ } #define RTEMS_SCHEDULER_TABLE_PRIORITY_SMP( name, obj_name ) \ { \ &SCHEDULER_PRIORITY_SMP_CONTEXT_NAME( name ).Base.Base.Base, \ SCHEDULER_PRIORITY_SMP_ENTRY_POINTS, \ RTEMS_ARRAY_SIZE( \ SCHEDULER_PRIORITY_SMP_CONTEXT_NAME( name ).Ready \ ) - 1, \ ( obj_name ) \ SCHEDULER_CONTROL_IS_NON_PREEMPT_MODE_SUPPORTED( false ) \ } #define RTEMS_SCHEDULER_TABLE_EDF_SMP( name, obj_name ) \ { \ &SCHEDULER_EDF_SMP_CONTEXT_NAME( name ).Base.Base.Base, \ SCHEDULER_EDF_SMP_ENTRY_POINTS, \ SCHEDULER_EDF_MAXIMUM_PRIORITY, \ ( obj_name ) \ SCHEDULER_CONTROL_IS_NON_PREEMPT_MODE_SUPPORTED( false ) \ }

六、其他调度器

除了上述调度器,还有基于CPU亲和性优先级的SMP调度器,如RTEMS_SCHEDULER_TABLE_PRIORITY_AFFINITY_SMP,他会根据CPU的亲和性来调整基于优先级的调度器,可以确保某个任务只允许运行在某个CPU上

还有基于抢占式的SMP调度器,并支持CPU的亲和性设置

七、系统默认调度器

系统默认调度器是优先级调度,其定义如下:

#if !defined(CONFIGURE_SCHEDULER_CBS) \ && !defined(CONFIGURE_SCHEDULER_EDF) \ && !defined(CONFIGURE_SCHEDULER_EDF_SMP) \ && !defined(CONFIGURE_SCHEDULER_PRIORITY) \ && !defined(CONFIGURE_SCHEDULER_PRIORITY_AFFINITY_SMP) \ && !defined(CONFIGURE_SCHEDULER_PRIORITY_SMP) \ && !defined(CONFIGURE_SCHEDULER_SIMPLE) \ && !defined(CONFIGURE_SCHEDULER_SIMPLE_SMP) \ && !defined(CONFIGURE_SCHEDULER_STRONG_APA) \ && !defined(CONFIGURE_SCHEDULER_USER) #if defined(RTEMS_SMP) && _CONFIGURE_MAXIMUM_PROCESSORS > 1 #define CONFIGURE_SCHEDULER_EDF_SMP #else #define CONFIGURE_SCHEDULER_PRIORITY #endif #endif

其配置作用如下:

#ifdef CONFIGURE_SCHEDULER /* * Ignore these warnings: * * - invalid use of structure with flexible array member * * - struct has no members */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" CONFIGURE_SCHEDULER; #pragma GCC diagnostic pop #endif const Scheduler_Control _Scheduler_Table[] = { CONFIGURE_SCHEDULER_TABLE_ENTRIES };

然后我们将宏定义展开,如下:

static struct { Scheduler_priority_Context Base; Chain_Control Ready[ ( 255 + 1 ) ]; } _Configuration_Scheduler_priority_dflt; const Scheduler_Control _Scheduler_Table[] = { { &_Configuration_Scheduler_priority_dflt.Base.Base, { _Scheduler_priority_Initialize, _Scheduler_priority_Schedule, _Scheduler_priority_Yield, _Scheduler_priority_Block, _Scheduler _priority_Unblock, _Scheduler_priority_Update_priority, _Scheduler_default_Map_priority, _Scheduler_default_Unmap_priority,

可以看到我们配置的默认调度器就是优先级调度,且有且就1个。还记得之前查看初始化代码的时候,我们在rtems_initialize_data_structures函数,会调用_Scheduler_Handler_initialization,其实现如下

void _Scheduler_Handler_initialization(void) { size_t n; size_t i; n = _Scheduler_Count; for ( i = 0 ; i < n ; ++i ) { const Scheduler_Control *scheduler; #if defined(RTEMS_SMP) Scheduler_Context *context; #endif scheduler = &_Scheduler_Table[ i ]; #if defined(RTEMS_SMP) context = _Scheduler_Get_context( scheduler ); #endif _ISR_lock_Initialize( &context->Lock, "Scheduler" ); ( *scheduler->Operations.initialize )( scheduler ); } }

这里会直接调用调度器的initialize函数。至此就开展调度器的初始化了