工控网首页
>

应用设计

>

基于WEC7的多核系统编程方法

基于WEC7的多核系统编程方法

  Windows Embedded Compact 7(WEC7)一个最重要的特性就是对多核处理器的支持(Symmetric Multi-Processing(SMP)),ESM6802是英创公司推出的基于Freescale  i.MX6DL双核处理器的高性能工控主板,预装正版WEC7嵌入式操作系统,并且内核启用了对SMP的支持。在多个程序同时执行的情况下,支持SMP的多核系统具有比单处理器更好的性能,因为不同的程序可以在不同的处理器上同时运行,支持SMP还可以实现在一个核心上执行硬实时应用程序,而用户界面(UI)或其它应用程序可在另一个核心上运行,以提高系统的效率。

  WEC7提供了一组处理多核系统上线程和处理器调度的SMP API接口函数:

  https://msdn.microsoft.com/en-us/library/gg154433(v=winembedded.70).aspx

  其中应用程序常用的SMP API如下所示:

 GetCurrentProcessorNumber  获取在调用此函数期间当前线程正在运行的处理器

 CeGetIdleTimeEx       获取指定处理器的空闲时间

 CeGetProcessAffinity     获取指定进程的进程关联

 CeGetThreadAffinity     获取指定线程的线程关联

 CeGetTotalProcessors    获取系统中的处理器核心总数

 CeSetProcessAffinity    为指定的进程设置处理器关联

 CeSetThreadAffinity     为指定的线程设置处理器关联

  默认情况下,WEC7系统会自动的将系统负载分配到CPU的所有核心上运行,应用程序不需要做任何设置。但根据不同的应用场景,应用程序也可以利用SMP API手动的设置每个进程、每个线程在指定的CPU核心上运行,这里以计算ESM6802 i.MX6DL CPU每个核心的负载为例,介绍WEC7 SMP API的使用方法。

  应用程序首先通过CeGetTotalProcessors函数获取当前系统总的处理器(核心)个数,然后根据CPU核心个数创建相同数量的CPUIdleMonitorThread应用线程用于计算CPU负载,在创建线程后通过CeSetThreadAffinity函数将所创建的线程固定在指定的CPU核心上运行。CPUIdleMonitorThread线程函数在执行时先调用GetCurrentProcessorNumber函数取得执行当前线程的CPU核,而后再利用CeGetIdleTimeEx函数最终计算出每个CPU核心的负载率。完整的例子代码如下:

  #include "stdafx.h"

  // time in seconds to run the monitor thread

  #define IDLE_MONITOR_TIME   100

  HANDLE g_hMonitorThreads[4];

  UINT32 CPUIdleMonitorThread(PVOID pContext)

  {

      UINT32 nCPUId = ((UINT32*)pContext)[0];

      UINT32 nRunTime = ((UINT32*)pContext)[1];

      UINT32 nIdleBefore, nIdleAfter, nIdleDiff, nIdlePercent;

      UINT32 nReturn = ERROR_SUCCESS;

     LARGE_INTEGER pcBefore = { 0, 0 };

      LARGE_INTEGER pcAfter = { 0, 0 };

      LARGE_INTEGER diff;

      LARGE_INTEGER freq;

      RETAILMSG(1, (L"[CPU%d] Run monitor thread for %d seconds\r\n", nCPUId, nRunTime));

     // The processor number is a 1-based index.

      QueryPerformanceFrequency(&freq);

      while (nRunTime > 0)

      {

          nCPUId = GetCurrentProcessorNumber();

          CeGetIdleTimeEx(nCPUId, (LPDWORD)&nIdleBefore);

          QueryPerformanceCounter(&pcBefore);

          Sleep(2000);

          QueryPerformanceCounter(&pcAfter);

         CeGetIdleTimeEx(nCPUId, (LPDWORD)&nIdleAfter);

          diff.QuadPart = (pcAfter.QuadPart - pcBefore.QuadPart) * 1000 / freq.QuadPart;

          nIdleDiff = nIdleAfter - nIdleBefore;

          nIdlePercent = nIdleDiff / 20;

          RETAILMSG(1, (L"[CPU%d] Sleep: 2000 ms (actual:%d ms)  Idle: %03d ms (CPU%d = %d%%)\r\n",

               nCPUId, diff.LowPart, nIdleDiff, nCPUId, 100 - nIdlePercent));

          nRunTime--;

      }

     SetEvent(g_hMonitorThreads[nCPUId - 1]);

      return nReturn;

  }

  int WINAPI WinMain(HINSTANCE hInstance,

                     HINSTANCE hPrevInstance,

                     LPTSTR     lpCmdLine,

                     int       nCmdShow)

  {

     UINT32 nCPUCount;

      UINT32 nTemp = 0;

      UINT32 i;

      UINT32 nParam[8] = { 1, IDLE_MONITOR_TIME, 2, IDLE_MONITOR_TIME, 3, IDLE_MONITOR_TIME, 4, IDLE_MONITOR_TIME };

      nCPUCount = CeGetTotalProcessors();

      for(i = 0; i < nCPUCount; i++)

          g_hMonitorThreads[i] = CreateEvent(NULL, TRUE, FALSE, NULL);

 

      nTemp = 1;

     CeSetThreadAffinity(GetCurrentThread(), 1);

      for (i = 1; i < nCPUCount; i++)

      {

          HANDLE hThread = CreateThread(

              NULL,

              0,

              (LPTHREAD_START_ROUTINE)CPUIdleMonitorThread,

              &nParam[i * 2],

              CREATE_SUSPENDED,

              NULL);

         if (NULL != hThread)

          {

              CeSetThreadAffinity(hThread, i + 1);

              ResumeThread(hThread);

              Sleep(0);

              CloseHandle(hThread);

              nTemp++;

          }

          else

          {

              SetEvent(g_hMonitorThreads[i]);

          }

      }

      CPUIdleMonitorThread(&nParam[0]);

      Sleep(2000);

      for(i = 0; i < nCPUCount; i++)

          WaitForSingleObject(g_hMonitorThreads[i], (IDLE_MONITOR_TIME + 5) * 1000);

      RETAILMSG(1, (L"[CPULOAD] Number of CPUs monitored: %d\r\n", nTemp));

      return 0;

  }

审核编辑(
王静
)
投诉建议

提交

查看更多评论
其他资讯

查看更多

Windows下STM32单片机eclipse编译环境搭建

Android Studio应用开发简介

WinCE工控主板WiFi解决方案

敬请关注成都英创微信公众号

WinCE工控主板通过PPI协议连接西门子PLC