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

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

本文以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 = http://www.mamicode.com/(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 = http://www.mamicode.com/(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.");}