概念
为周期性任务解决多任务调度冲突的一种非常好的方法是速率单调调度(Rate Monotonic Scheduling RMS),RMS 基于任务的周期指定优先级。
在 RMS 中,最短周期的任务具有最高优先级,次短周期的任务具有次高优先级,依次类推。当同时有多个任务可以被执行时,最短周期的任务被优先执行。如果将任务的优先级视为速率的函数,那么这就是一个单调递增函数。
接口
sylixos提供两种类型的RMS调度器接口,一个是sylixos内核自带接口,一个是POSIX标准接口,这两类都可实现周期任务,但不要混用。
sylixos内核原生接口
/*********************************************************************************************************
** 函数名称: API_RmsCreate
** 功能描述: 建立一个精度单调调度器
** 输 入 :
** pcName 名字
** ulOption 选项
** pulId Id 号
** 输 出 :
*********************************************************************************************************/
LW_OBJECT_HANDLE API_RmsCreate (CPCHAR pcName,
ULONG ulOption,
LW_OBJECT_ID *pulId)
/*********************************************************************************************************
** 函数名称: API_RmsCancel
** 功能描述: 指定精度单调调度器停止工作
** 输 入 :
** ulId RMS 句柄
** 输 出 :
*********************************************************************************************************/
ULONG API_RmsCancel (LW_OBJECT_HANDLE ulId)
/*********************************************************************************************************
** 函数名称: API_RmsExecTimeGet
** 功能描述: 获得当前任务从调用 API_RmsPeriod() 函数到目前执行的时间,单位为: Tick.
** 输 入 :
** ulId RMS 句柄
** pulExecTime 运行时间
** 输 出 :
*********************************************************************************************************/
ULONG API_RmsExecTimeGet (LW_OBJECT_HANDLE ulId, ULONG *pulExecTime)
/*********************************************************************************************************
** 函数名称: API_RmsPeriod
** 功能描述: 指定精度单调调度器开始按固定周期工作
** 输 入 :
** ulId RMS 句柄
** ulPeriod 程序段执行周期
** 输 出 :
*********************************************************************************************************/
ULONG API_RmsPeriod (LW_OBJECT_HANDLE ulId, ULONG ulPeriod)
/*********************************************************************************************************
** 函数名称: API_RmsStatus
** 功能描述: 获得精度单调调度器的状态
** 输 入 :
** ulId RMS 句柄
** pucStatus 名字缓冲区 可以为 NULL
** pulTimeLeft 等待剩余时间 可以为 NULL
** pulOwnerId 所有者 ID 可以为 NULL
** 输 出 :
*********************************************************************************************************/
ULONG API_RmsStatus (LW_OBJECT_HANDLE ulId,
UINT8 *pucStatus,
ULONG *pulTimeLeft,
LW_OBJECT_HANDLE *pulOwnerId)
/*********************************************************************************************************
** 函数名称: API_RmsDeleteEx
** 功能描述: 删除精度单调调度器
** 输 入 :
** pulId RMS 句柄指针
** bForce 强制删除
** 输 出 :
*********************************************************************************************************/
ULONG API_RmsDeleteEx (LW_OBJECT_HANDLE *pulId, BOOL bForce)
POSIX标准接口
作为 POSIX 的扩展,SylixOS 提供了下面一组函数来实现 POSIX RMS 调度器,相比之前的 RMS 实现,下面的函数更加易用且时间精度更高(纳秒级)。
/*********************************************************************************************************
** 函数名称: sched_rms_init
** 功能描述: 初始化 RMS 调度器
** 输 入 : prms RMS 调度器
** thread 需要调用 RMS 的线程.
** 输 出 : 是否初始化成功
*********************************************************************************************************/
int sched_rms_init (sched_rms_t *prms, pthread_t thread)
/*********************************************************************************************************
** 函数名称: sched_rms_destroy
** 功能描述: 删除 RMS 调度器
** 输 入 : prms RMS 调度器
** 输 出 : 是否删除成功
*********************************************************************************************************/
int sched_rms_destroy (sched_rms_t *prms)
/*********************************************************************************************************
** 函数名称: sched_rms_period
** 功能描述: 删除 RMS 调度器
** 输 入 : prms RMS 调度器
** period RMS 周期
** 输 出 : 0 表示正确
** error == EINTR 表示被信号激活.
*********************************************************************************************************/
int sched_rms_period (sched_rms_t *prms, const struct timespec *period)
调用 sched_rms_init 函数将初始化参数 prms 指定的 RMS 调度器,与 Lw_Rms_Create函数不同的是,前者由应用程序创建一个 sched_rms_t 类型的 RMS 调度器,然后调用sched_rms_init 函数来初始化这个调度器,也就是说,此调度器将由应用程序创建和销毁,而后者创建的 RMS 调度器则由内核管理,也即应用程序不会直接管理所使用的调度器。
例程
SylixOS原生接口例程
#include <sched_rms.h>
#include <pthread.h>
/*********************************************************************************************************
** 函数名称: rms_thread
** 功能描述: 线程函数
** 输 入 : arg 传入的参数
** 输 出 : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
void *rms_thread (void *arg)
{
LW_OBJECT_HANDLE hRms;
ULONG ulPeriod = 5 * CLOCKS_PER_SEC;
struct timespec tv;
hRms = API_RmsCreate("rmstest", 0, NULL);
while (1) {
if (API_RmsPeriod(hRms, ulPeriod) != 0) {
fprintf(stderr, "sched_rms_period error\n");
break;
}
lib_clock_gettime(CLOCK_MONOTONIC, &tv);
fprintf(stdout, "[%16llu]\n", (tv.tv_sec * 1000000 + tv.tv_nsec / 1000));
sleep(1);
}
return (NULL);
}
/*********************************************************************************************************
** 函数名称: main
** 功能描述: 主函数
** 输 入 : argc,argv
** 输 出 : ERROR
** 全局变量:
** 调用模块:
*********************************************************************************************************/
int main (int argc, char *argv[])
{
pthread_t tid;
int ret;
ret = pthread_create(&tid, NULL, rms_thread, NULL);
if (ret < 0) {
fprintf(stderr, "pthread_create error.\n");
return (-1);
}
pthread_join(tid, NULL);
return (0);
}
POSIX标准接口例程
#include <sched_rms.h>
#include <pthread.h>
/*********************************************************************************************************
全局变量定义
*********************************************************************************************************/
sched_rms_t rms;
/*********************************************************************************************************
** 函数名称: rms_thread
** 功能描述: 线程函数
** 输 入 : arg 传入的参数
** 输 出 : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
void *rms_thread (void *arg)
{
struct timespec *period = (struct timespec *)arg;
struct timespec tv;
sched_rms_init(&rms, pthread_self());
while (1) {
if (sched_rms_period(&rms, period) != 0) {
fprintf(stderr, "sched_rms_period error\n");
break;
}
lib_clock_gettime(CLOCK_MONOTONIC, &tv);
fprintf(stdout, "[%16llu]\n", (tv.tv_sec * 1000000 + tv.tv_nsec / 1000));
sleep(1);
}
return (NULL);
}
/*********************************************************************************************************
** 函数名称: main
** 功能描述: 主函数
** 输 入 : argc,argv
** 输 出 : ERROR
** 全局变量:
** 调用模块:
*********************************************************************************************************/
int main (int argc, char *argv[])
{
pthread_t tid;
int ret;
struct timespec period;
period.tv_nsec = 0;
period.tv_sec = 5;
ret = pthread_create(&tid, NULL, rms_thread, (void *)&period);
if (ret < 0) {
fprintf(stderr, "pthread_create error.\n");
return (-1);
}
pthread_join(tid, NULL);
sched_rms_destroy(&rms);
return (0);
}
执行结果