本文以windows实时拓展Kithara RTS安装目录下的smp文件夹内的TaskSimple项目为例,解读Kithara
RTS的实时多任务编程方法。
该项目只有一个工程TaskSimple,工程内的TaskSimple.cpp文件实现了主要功能,使用了Kithara
RTS的kernel模块和Task模块
TaskSimple.cpp文件主要由5部分组成,共享内存结构体,三个任务回调函数,一个主函数runSample
共享内存结构体:
//------ CallBackData ------
struct CallBackData {
Handle hTaskA_;
Handle hTaskB_;
Handle hTaskC_;
Handle hPipe_;
};
CallBackData内部有3个任务句柄和一个用于数据交互的hPipe_对象。
///////////////////////////////////////////////////////////////////////////
runSample函数的主要功能代码:
ksError = KS_openDriver(//打开驱动,这是使用Kithara RTS的第一步
pCustomerNumber); // Customer number
if (ksError) {
outputErr(ksError, "KS_openDriver", "Maybe incorrect customer number?");
return;
}//------------------------------------------------------------------------------------------------------------
// Allocation of Sharedmem
//------------------------------------------------------------------------------------------------------------CallBackData* pAppPtr;
CallBackData* pSysPtr;
ksError = KS_createSharedMem(//创建共享内存
(void**)&pAppPtr, // App Pointer,应用层指针,只能在应用层中使用
(void**)&pSysPtr, // Sys Pointer,内核层指针,只能在内核层中使用
NULL, // Name,名称
sizeof(CallBackData), // Size,共享内存空间大小
0); // Flags,标志位,这里设置为0即可
//注意如果内核层使用了pAppPtr或者应用层使用了pSysPtr会造成系统崩溃
if (ksError != KS_OK) {
outputErr(ksError, "KS_createSharedMem", "Failed to allocate shared memory");
KS_closeDriver();
return;
}//------------------------------------------------------------------------------------------------------------
// For data transfer we use a pipe.
//------------------------------------------------------------------------------------------------------------ksError = KS_createPipe(//创建数据管道,用于任务之间的数据交互
&pAppPtr->hPipe_, // Pipe Handle ,句柄,在共享内存中
"MyTaskSimplePipe", // Name,名称
sizeof(char), // Item size, here size of pointer,单位大小
9, // Item count,管道长度
NULL, // Object to signal,触发对象,没有使用设置为null(空)
0); // Flags,标志位设置为0
if (ksError != KS_OK) {
outputErr(ksError, "KS_createPipe", "Unable to create pipe!");
KS_closeDriver();
return;
}//------------------------------------------------------------------------------------------------------------
// Now we create the callbacks. The callback contains the KSF_DIRECT_EXEC: - execution on kernel level
//------------------------------------------------------------------------------------------------------------
//下面将3个函数体映射为3个回调函数,
Handle hCallbackA;
ksError = KS_createCallBack(//创建回调函数
&hCallbackA, // Address of callback handle,回调函数句柄
_callBackA, // Callback function,回调函数本体
pSysPtr, // Reference parameter to the callback,回调函数的参数
KSF_DIRECT_EXEC, // Flags,直接执行
0); // Priority (only on user level)
if (ksError != KS_OK) {
outputErr(ksError, "KS_createCallBack", "Failed to create callback");
KS_closeDriver();
return;
}
//参数pSysPtr对应回调函数的pArgs,由于回调函数运行在内核层因此其实用的参数也必须位于内核层
//pSysPtr是内核层参数,pAppPtr是用户层参数Handle hCallbackB;
ksError = KS_createCallBack(
&hCallbackB, // Address of callback handle
_callBackB, // Callback function
pSysPtr, // Reference parameter to the callback
KSF_DIRECT_EXEC, // Flags
0); // Priority (only on user level)
if (ksError != KS_OK) {
outputErr(ksError, "KS_createCallBack", "Failed to create callback");
KS_closeDriver();
return;
}Handle hCallbackC;
ksError = KS_createCallBack(
&hCallbackC, // Address of callback handle
_callBackC, // Callback function
pSysPtr, // Reference parameter to the callback
KSF_DIRECT_EXEC, // Flags
0); // Priority (only on user level)
if (ksError != KS_OK) {
outputErr(ksError, "KS_createCallBack", "Failed to create callback");
KS_closeDriver();
return;
}//------------------------------------------------------------------------------------------------------------
// Create the tasks
// Task B and Task C are created with KSF_DONT_START, so they are suspended.
// Task A executes immediately after creation.
//------------------------------------------------------------------------------------------------------------outputTxt(" ");
outputTxt("Creating tasks.");//创建任务
ksError = KS_createTask(
&pAppPtr->hTaskB_, // Address of task handle,任务句柄
hCallbackB, // Callback handle,回调函数
250, // Priority,优先级
KSF_DONT_START); // Flags, don‘t start now,标志位,不立即启动
//任务句柄存入共享内存结构体中,任务执行的本质是执行hCallbackB回调函数
//优先级为250(数值越大优先级越高)
//以下两个任务的创建过程与本例相似,但是优先级不同
if (ksError != KS_OK) {
outputErr(ksError, "KS_createTask", "Failed to create task");
KS_closeDriver();
return;
}ksError = KS_createTask(
&pAppPtr->hTaskC_, // Address of task handle
hCallbackC, // Callback handle
150, // Priority
KSF_DONT_START); // Flags, don‘t start now
if (ksError != KS_OK) {
outputErr(ksError, "KS_createTask", "Failed to create task");
KS_closeDriver();
return;
}ksError = KS_createTask(
&pAppPtr->hTaskA_, // Address of task handle
hCallbackA, // Callback handle
200, // Priority
0); // Flags, start immediately立即启动
if (ksError != KS_OK) {
outputErr(ksError, "KS_createTask", "Failed to create task");
KS_closeDriver();
return;
}waitTime(1000 * ms);//延时1s,等待3个任务都执行完毕
outputTxt(" ");
outputTxt("The tasks completed their work.");char pBuf[10];
int length;
KS_getPipe(//读取pipe数据到pBuf中
pAppPtr->hPipe_, // Pipe handle
pBuf, // Pointer to buffer
9, // Buffer size
&length, // Pointer to int to write gotten length
0); // Flags
pBuf[length] = 0;outputTxt("Expected output : ABBBCBBAC");
outputTxt("Actual output : ", false);
outputTxt(pBuf);//打印pBuf中的字符串
outputTxt(" ");
//三个回调函数
首先TaskA运行,TaskA激活TaskB,由于TaskB优先级比TaskA高,因此TaskB运行
然后TaskB挂起TaskA,激活TaskC,然后挂起自身,此时只有低优先级的TaskC可以执行
然后TaskC激活TaskB,TaskB优先级比TaskC高,此时TaskB执行,然后激活TaskA,但是TaskA优先级比TaskB低因此不会被立即执行
TaskB执行完毕之后,由于TaskA优先级比TaskC高,此时TaskA执行
TaskA执行完毕之后,TaskC执行,最后三个任务都执行完成。
等待1s后,打印输出任务执行过程中向pipe写入的数据“ABBBCBBAC”
//------ _callBackA ------
static Error __stdcall _callBackA(void* pArgs, void* pContext) {
CallBackData* pData = (CallBackData*)pArgs;const char chr = ‘A‘;
KS_putPipe(//向pipe中写入‘A‘
pData->hPipe_, // Pipe handle
&chr, // Address of packet
1, // One item
NULL, // Number of bytes transmitted
0); // Flags, here noneKS_triggerTask(//激活任务b,由于b优先级比a高,调到b中执行
pData->hTaskB_); // Task handleKS_putPipe(pData->hPipe_, &chr, 1, NULL, 0);//写入‘a’
KS_exitTask(//退出当前任务,此时a,b都执行完毕,则调到c中执行
NULL, // Task handle, null for current task
0); // Exit codereturn KS_OK;
}//------ _callBackB ------
static Error __stdcall _callBackB(void* pArgs, void* pContext) {
CallBackData* pData = (CallBackData*)pArgs;const char chr = ‘B‘;
KS_putPipe(pData->hPipe_, &chr, 1, NULL, 0);//向pipe中写入‘B’
KS_triggerTask(//激活c,但是c优先级低,不能被执行
pData->hTaskC_); // Task handleKS_putPipe(pData->hPipe_, &chr, 1, NULL, 0);//继续写入‘b’
KS_suspendTask(//将任务A挂起
pData->hTaskA_); // Task handleKS_putPipe(pData->hPipe_, &chr, 1, NULL, 0);//继续写入‘b’
KS_suspendTask(//把自身挂起,即把b挂起,此时A也挂起,因此调到c中执行
NULL); // Task handle, null for current taskKS_putPipe(pData->hPipe_, &chr, 1, NULL, 0);//写入‘b’
KS_resumeTask(//恢复a
pData->hTaskA_); // Task handleKS_putPipe(pData->hPipe_, &chr, 1, NULL, 0);//写入‘b‘
return KS_OK;//此时TaskB执行完毕,而a和c都处于就绪状态,而a优先级高于c,因此调到a中执行
}//------ _callBackC ------
static Error __stdcall _callBackC(void* pArgs, void* pContext) {
CallBackData* pData = (CallBackData*)pArgs;const char chr = ‘C‘;
KS_putPipe(pData->hPipe_, &chr, 1, NULL, 0);//向pipe中写入‘c’
KS_resumeTask(//激活TaskB,由于TaskB优先级比TaskC优先级高,调到TaskB中执行
pData->hTaskB_); // Task handleKS_putPipe(pData->hPipe_, &chr, 1, NULL, 0);//写入‘c’
KS_exitTask(//退出任务,至此3个任务都执行完毕
NULL, // Task handle, null for current task
0); // Exit codereturn KS_OK;
}
多任务编程----Kithara RTS工程源码解析