码迷,mamicode.com
首页 > 其他好文 > 详细

配置一个逻辑CPU专用于实时任务----Kithara RTS工程源码分析

时间:2014-06-26 23:17:15      阅读:339      评论:0      收藏:0      [点我收藏+]

标签:des   style   class   blog   code   tar   

本文以windows实时拓展Kithara RTS安装目录下的smp文件夹内的DedicatedRealTimeTask项目为例,讲解使实时任务以独占一个逻辑CPU的方式运行,并实现任务间的同步。

目前多核计算机已经普及,多数的PC都是多核的。针对这种多核结构,我们设想把计算机划分为不同的硬件区间,其中一部分用于被实时任务专用,另一部分是被windows使用的,两者之间互不干扰,这样实时任务可以实现更好的实时性能。这种硬件划分,一般是按照物理CPU的核心数,即逻辑CPU的数量来配置的。可以配置一个CPU外加部分IO硬件资源给实时任务专用,Kithara RTS的Dedicated模块就是实现这种功能。

当然,在多核PC上也可以不用Dedicated模块,实时任务和非实时任务将会共享相同的硬件资源,和之前的单核PC上的方法相同。不过实时性能会稍微弱一些。

该项目源码主要使用了三个模块:Kernel模块,Task模块,Timer模块,Realtime模块,Clock模块。

该项目主要包括,一个主函数runSample和两个回调函数。任务A为一直运行;任务B为定时器回调函数,周期性运行,运行时会独占一个未被WINDOWS使用的逻辑CPU;任务A的运行过程中会阻塞,等待任务B的触发信号后才能继续运行。周期性运行的任务B每运行1000次激活信号,然后任务A才能继续运行。

// Used Modules: Kernel, Task, Timer, RealTime, Clock(使用到的5个模块)
//
// Descript.: Sample show how to use a dedicated CPU for a task and how it can be syncronized with other tasks.
// 描述: 任务使用专用CPU,与其他任务同步

// Purpose:
//
// This example shows how to use a dedicated CPU for a task and how it can be syncronized with other tasks.
//该例子展示了如何用专用CPU执行任务,如何与其他任务实现同步
// The task on the dedicated CPU will run with 100 kilo Herz and sets an event periodically. Addtionaly a
// semaphore is requested. The other task will wait for this event. After wating for the event a 1000 times the
// semaphore is requested which will block the task on the dedicated CPU.
// 在专用CPU的任务运行频率为100kHz,并且周期性地设置任务。另外还需要使用一个信号。其他任务等待该事件。等待1000次之
// 后,信号将会阻止运行在专用CPU上的任务。
//##############################################################################################################

#include "..\_KitharaSmp\_KitharaSmp.h"

const char* pCustomerNumber = "DEMO";

//--------------------------------------------------------------------------------------------------------------
// This is a user defined argument structure to the callback routine.
// You are free to define your own arguments in any record/class.
//--------------------------------------------------------------------------------------------------------------

//------ CallBackData ------用于回调函数的结构体,本质为存入共享内存的结构体
struct CallBackData {
  int counterTaskA_;
  int counterTaskB_;
  KSHandle hTaskA_;
  KSHandle hTaskB_;
  KSHandle hEvent_;
  KSHandle hSema_;
};

const int us = 10;//时间us的数值当量

//--------------------------------------------------------------------------------------------------------------
// These are the user defined callback routines.
//--------------------------------------------------------------------------------------------------------------

//------ _callBackA ------
static Error __stdcall _callBackA(void* pArgs, void* pContext) {//回调函数A
  CallBackData* pData = (CallBackData*)pArgs;//指针转换,空指针类型转换为特定的指针类型

  while (pData->counterTaskA_ < 1000) {                //循环1000次
    Error ksError = KS_waitForEvent(     //等待事件pData->hEvent触发,处于阻塞中,函数的执行结果有两种,一种是事件在规定超时时间内被触发,一种是在超时时间内没有被触发,函数将会返回错误,即ksError的值不是KS_OK.               
                      pData->hEvent_,                   // Event handle,事件句柄
                      0,                                // Flags, here zero
                      30000 * ms);                      // Timeout value in 100-ns-units(等待30s),超时时间
    if (ksError != KS_OK) {
      return ksError;
    }

    ++pData->counterTaskA_;//更新共享内存中的计数值counterTaskA_
  }

  return KS_requestSemaphore( //用来请求任务同步的信号量,等待1s,超时则反馈错误
           pData->hSema_,                               // Handle of a semaphore
           1000 * ms);                                  // Timeout value in 100-ns-units
}

//------ _callBackB ------
static Error __stdcall _callBackB(void* pArgs, void* pContext) {//回调函数B
  CallBackData* pData = (CallBackData*)pArgs;

  Error ksError = KS_requestSemaphore(pData->hSema_, 10000 * ms);
  if (ksError != KS_OK) {
    return ksError;
  }

  ++pData->counterTaskB_;

  if (pData->counterTaskB_ % 1000 == 0) {               //每循环1000次,创建事件
    Error ksError = KS_setEvent(
                      pData->hEvent_);                  // Event handle
    if (ksError != KS_OK)
      return ksError;
  }

  return KS_releaseSemaphore(
           pData->hSema_);                              // Handle of a semaphore
}


//--------------------------------------------------------------------------------------------------------------
// This is the main program
//--------------------------------------------------------------------------------------------------------------

void runSample() {
//////////////////以下为初始化代码,和大部分Kithara RTS源码类似//////////////////////////// outputTxt(
"***** Kithara example program ‘DedicatedRealTimeTask‘ *****"); Error ksError; //------------------------------------------------------------------------------------------------------------ // Opening the driver is always the first step! After that, we can use other functions. If the opening fails, // no other function can be called. // // This function takes your customer number with Kithara (or "DEMO" or "BETA" if applicable) as a parameter. //------------------------------------------------------------------------------------------------------------ ksError = KS_openDriver( //打开Kithara驱动 pCustomerNumber); // Customer number if (ksError) { outputErr(ksError, "KS_openDriver", "Maybe incorrect customer number?"); return; } //------------------------------------------------------------------------------------------------------------ // First, we will determine how many CPU are shared with windows and where to find a dedicated CPU //------------------------------------------------------------------------------------------------------------ KSSystemInformation systemInfo; // KSSystemInformation instace systemInfo.structSize = sizeof(KSSystemInformation); // do not forget to init structSize! ksError = KS_getSystemInformation( &systemInfo, // Pointer to information structure 0); // Flags, here zero outputTxt(""); outputDec(systemInfo.numberOfCPUs, "Number of CPUs in the PC = "); outputDec(systemInfo.numberOfSharedCPUs, "Number of CPUs, which are shared by Windows and Realtime = "); outputTxt(""); int dedicatedCPUsAvail = systemInfo.numberOfCPUs - systemInfo.numberOfSharedCPUs; if (dedicatedCPUsAvail < 1) { outputTxt("No dedicated CPU avail, please boot your system with less CPUs"); KS_closeDriver(); return; } outputDec(dedicatedCPUsAvail, "Number of dedicated CPUs = "); outputTxt(""); // the number of shared CPUs is the index of the first dedicated CPU as well int dedicatedCPU = inputDec("Which dedicated CPU shall be used ", systemInfo.numberOfSharedCPUs); outputTxt(""); ////////////////以下为关键代码/////////////// //------------------------------------------------------------------------------------------------------------ // Allocation of Sharedmem and init the counter with zero //------------------------------------------------------------------------------------------------------------ CallBackData* pAppPtr; CallBackData* pSysPtr; ksError = KS_createSharedMem(//创建共享内存,用于用户层与内核层进行通信,共享内存为结构体CallBackData (void**)&pAppPtr, // App Pointer (void**)&pSysPtr, // Sys Pointer NULL, // Name sizeof(CallBackData), // Size 0); // Flags if (ksError != KS_OK) { outputErr(ksError, "KS_createSharedMem", "Failed to allocate shared memory"); KS_closeDriver(); return; } pAppPtr->counterTaskA_ = 0; pAppPtr->counterTaskB_ = 0; //------------------------------------------------------------------------------------------------------------ // Now we create the event and semaphore //------------------------------------------------------------------------------------------------------------ ksError = KS_createEvent(//创建事件 &pAppPtr->hEvent_, // Pointer to an event handle. NULL, // Global name of the event will be set by the driver KSF_KERNEL_EXEC); // Creates an event for blocking a task该标志位表示任务是来终止一个事件的 if (ksError != KS_OK) { outputErr(ksError, "KS_createEvent", "Failed to create an task event"); KS_closeDriver(); return; } ksError = KS_createSemaphore(//创建信号量 用于任务同步 &pAppPtr->hSema_, // Pointer to a semaphore handle 1, // Maximum semaphore count 1, // Initial semaphore count 0); // Flags, here zero if (ksError != KS_OK) { outputErr(ksError, "KS_createSemaphore", "Failed to create a semaphore"); KS_closeDriver(); return; } //------------------------------------------------------------------------------------------------------------ // Now we create the callbacks. The callback contains the KSF_DIRECT_EXEC: - execution on kernel level //------------------------------------------------------------------------------------------------------------ KSHandle hCallbackA; ksError = KS_createCallBack( //创建回调函数A &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; } KSHandle hCallbackB; ksError = KS_createCallBack( //创建回调函数B &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; } //------------------------------------------------------------------------------------------------------------ // Now we create the for the windows shared CPU 0, which will wait for the event from the task on the // dedicated CPU.在CPU 0 上运行的task,在dedicatedCPU上的任务运行完毕之后,运行该任务 //------------------------------------------------------------------------------------------------------------ ksError = KS_createTask(//创建任务A,回调函数A,从现在开始在内核中开始执行 &pAppPtr->hTaskA_, // Address of task handle,任务句柄存入共享内存结构体中,用该任务执行hCallbackA回调函数 hCallbackA, // Callback handle 130, // Priority 优先级,数值越大,优先级越高 0); // Flags,0表示立即执行 if (ksError != KS_OK) { outputErr(ksError, "KS_createTask", "Failed to create task"); KS_closeDriver(); return; } //------------------------------------------------------------------------------------------------------------ // Create the second task which whill runs on the dedicated CPU运行在dedicatedCPU上的程序 // Before we create the task which will run on the dedicated CPU we need to boot this CPU with // KS_setTargetProcessor. KS_setTargetProcessor also sets the target processor for the Task which will be // created from now on.在运行改程序之前,我们需要用函数KS_setTargetProcessor配置CPU引导程序
// 该函数有两个功能,一个是启动未被WINDOWS使用的CPU,另一个功能是指定该CPU专用于实时任务的运行。该函数之后的代码都是在这个CPU上执行的。
//------------------------------------------------------------------------------------------------------------ ksError = KS_setTargetProcessor( dedicatedCPU, // Logical processor number, counting starts with zero 0); // Flags, here zero if (ksError != KS_OK) { outputErr(ksError, "KS_setTargetProcessor", "Failed to boot dedicated CPU"); KS_closeDriver(); return; } ksError = KS_createTask( // 创建任务B &pAppPtr->hTaskB_, // Address of task handle任务句柄存入共享内存结构体中,用该任务执行hCallbackA回调函数 hCallbackB, // Callback handle 130, // Priority KSF_DONT_START); // Dont start the task, a time will do that 不立即执行,有触发时执行 if (ksError != KS_OK) { outputErr(ksError, "KS_createTask", "Failed to create task"); KS_closeDriver(); return; } //------------------------------------------------------------------------------------------------------------ // Create a 100 kHz Timer for the task on the dedicated CPU
// 为专用CPU上的任务创建一个100kHz的定时器,即该定时器的定时周期为10us
//------------------------------------------------------------------------------------------------------------ KSHandle hTimer; ksError = KS_createTimer( // 创建定时器 &hTimer, // Address of timer handle 10 * us, // Timer period in 100-ns-units,定时周期 pAppPtr->hTaskB_, // Task handle回调函数B,每个周期回调一次 KSF_REALTIME_EXEC); // Flags, here real-time execution if (ksError != KS_OK) { outputErr(ksError, "KS_createTimer", "Unable to create the timer!"); KS_closeDriver(); return; } outputTxt("The tasks are now running ..."); outputTxt(""); while (pAppPtr->counterTaskA_ < 1000) { outputDec(pAppPtr->counterTaskA_, "\rCounter Task A = ", " - ", false); outputDec(pAppPtr->counterTaskB_, "Counter Task B = ", "", false); waitTime(25 * ms); } outputDec(pAppPtr->counterTaskA_, "\rCounter Task A = ", " - ", false); outputDec(pAppPtr->counterTaskB_, "Counter Task B = ", "", false); outputTxt(""); outputTxt("");

///////////////////////以下为资源回收代码//////////////////////////////////
//------------------------------------------------------------------------------------------------------------ // Stop the timer //------------------------------------------------------------------------------------------------------------ ksError = KS_stopTimer( hTimer); // Timer handle if (ksError != KS_OK) outputErr(ksError, "KS_stopTimer", "Unable to stop the timer!"); //------------------------------------------------------------------------------------------------------------ // Remove the timer //------------------------------------------------------------------------------------------------------------ ksError = KS_removeTimer( hTimer); // Timer handle if (ksError != KS_OK) outputErr(ksError, "KS_removeTimer", "Unable to remove timer"); //------------------------------------------------------------------------------------------------------------ // Remove event and semaphore //------------------------------------------------------------------------------------------------------------ ksError = KS_closeEvent( pAppPtr->hEvent_); // Event handle if (ksError != KS_OK) outputErr(ksError, "KS_closeEvent", "Unable to close event"); ksError = KS_removeSemaphore( pAppPtr->hSema_); // Semaphore handle if (ksError != KS_OK) outputErr(ksError, "KS_removeSemaphore", "Unable to remove semaphore"); //------------------------------------------------------------------------------------------------------------ // Remove the tasks //------------------------------------------------------------------------------------------------------------ ksError = KS_removeTask( pAppPtr->hTaskA_); // Task handle if (ksError != KS_OK) outputErr(ksError, "KS_removeTask", "Unable to remove task"); ksError = KS_removeTask( pAppPtr->hTaskB_); // Task handle if (ksError != KS_OK) outputErr(ksError, "KS_removeTask", "Unable to remove task"); //------------------------------------------------------------------------------------------------------------ // Remove the callbacks //------------------------------------------------------------------------------------------------------------ ksError = KS_removeCallBack( hCallbackA); // Callback handle if (ksError != KS_OK) outputErr(ksError, "KS_removeCallBack", "Unable to remove the callback!"); ksError = KS_removeCallBack( hCallbackB); // Callback handle if (ksError != KS_OK) outputErr(ksError, "KS_removeCallBack", "Unable to remove the callback!"); //------------------------------------------------------------------------------------------------------------ // Remove the shared memory //------------------------------------------------------------------------------------------------------------ ksError = KS_freeSharedMem( pAppPtr); // Application pointer if (ksError != KS_OK) outputErr(ksError, "KS_freeSharedMem", "Unable to remove shared memory!"); //------------------------------------------------------------------------------------------------------------ // At last we have to close the driver to free any allocated resources. //------------------------------------------------------------------------------------------------------------ ksError = KS_closeDriver(); if (ksError != KS_OK) outputErr(ksError, "KS_closeDriver", "Unable to close the driver!"); waitTime(500 * ms); outputTxt("End of program ‘DedicatedRealTimeTask‘. Press <enter> to close."); }

 

配置一个逻辑CPU专用于实时任务----Kithara RTS工程源码分析,布布扣,bubuko.com

配置一个逻辑CPU专用于实时任务----Kithara RTS工程源码分析

标签:des   style   class   blog   code   tar   

原文地址:http://www.cnblogs.com/sunvhao/p/3807682.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!