首页 > 代码库 > 多任务编程----Kithara RTS工程源码解析

多任务编程----Kithara RTS工程源码解析

本文以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 = http://www.mamicode.com/(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 none 
  
  KS_triggerTask(//激活任务b,由于b优先级比a高,调到b中执行 
    pData->hTaskB_);                                    // Task handle

  KS_putPipe(pData->hPipe_, &chr, 1, NULL, 0);//写入‘a’

  KS_exitTask(//退出当前任务,此时a,b都执行完毕,则调到c中执行 
    NULL,                                               // Task handle, null for current task 
    0);                                                 // Exit code

  return KS_OK; 
}

//------ _callBackB ------ 
static Error __stdcall _callBackB(void* pArgs, void* pContext) { 
  CallBackData* pData = http://www.mamicode.com/(CallBackData*)pArgs;

  const char chr = B;

  KS_putPipe(pData->hPipe_, &chr, 1, NULL, 0);//向pipe中写入‘B’

  KS_triggerTask(//激活c,但是c优先级低,不能被执行 
    pData->hTaskC_);                                    // Task handle

  KS_putPipe(pData->hPipe_, &chr, 1, NULL, 0);//继续写入‘b’

  KS_suspendTask(//将任务A挂起 
    pData->hTaskA_);                                    // Task handle

  KS_putPipe(pData->hPipe_, &chr, 1, NULL, 0);//继续写入‘b’

  KS_suspendTask(//把自身挂起,即把b挂起,此时A也挂起,因此调到c中执行 
    NULL);                                              // Task handle, null for current task

  KS_putPipe(pData->hPipe_, &chr, 1, NULL, 0);//写入‘b’

  KS_resumeTask(//恢复a 
    pData->hTaskA_);                                    // Task handle

  KS_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 = http://www.mamicode.com/(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 handle

  KS_putPipe(pData->hPipe_, &chr, 1, NULL, 0);//写入‘c’

  KS_exitTask(//退出任务,至此3个任务都执行完毕 
    NULL,                                               // Task handle, null for current task 
    0);                                                 // Exit code

  return KS_OK; 
}