Windows Embedded Compact 7(WEC7)一個最重要的特性就是對多核處理器的支持(Symmetric Multi-Processing(SMP)),ESM6802是英創(chuàng)公司推出的基于Freescale i.MX6DL雙核處理器的高性能工控主板,預裝正版WEC7嵌入式操作系統(tǒng),并且內(nèi)核啟用了對SMP的支持。在多個程序同時執(zhí)行的情況下,支持SMP的多核系統(tǒng)具有比單處理器更好的性能,因為不同的程序可以在不同的處理器上同時運行,支持SMP還可以實現(xiàn)在一個核心上執(zhí)行硬實時應用程序,而用戶界面(UI)或其它應用程序可在另一個核心上運行,以提高系統(tǒng)的效率。
WEC7提供了一組處理多核系統(tǒng)上線程和處理器調(diào)度的SMP API接口函數(shù):
https://msdn.microsoft.com/en-us/library/gg154433(v=winembedded.70).aspx
其中應用程序常用的SMP API如下所示:
GetCurrentProcessorNumber | 獲取在調(diào)用此函數(shù)期間當前線程正在運行的處理器 |
CeGetIdleTimeEx | 獲取指定處理器的空閑時間 |
CeGetProcessAffinity | 獲取指定進程的進程關聯(lián) |
CeGetThreadAffinity | 獲取指定線程的線程關聯(lián) |
CeGetTotalProcessors | 獲取系統(tǒng)中的處理器核心總數(shù) |
CeSetProcessAffinity | 為指定的進程設置處理器關聯(lián) |
CeSetThreadAffinity | 為指定的線程設置處理器關聯(lián) |
默認情況下,WEC7系統(tǒng)會自動的將系統(tǒng)負載分配到CPU的所有核心上運行,應用程序不需要做任何設置。但根據(jù)不同的應用場景,應用程序也可以利用SMP API手動的設置每個進程、每個線程在指定的CPU核心上運行,這里以計算ESM6802 i.MX6DL CPU每個核心的負載為例,介紹WEC7 SMP API的使用方法。
應用程序首先通過CeGetTotalProcessors函數(shù)獲取當前系統(tǒng)總的處理器(核心)個數(shù),然后根據(jù)CPU核心個數(shù)創(chuàng)建相同數(shù)量的CPUIdleMonitorThread應用線程用于計算CPU負載,在創(chuàng)建線程后通過CeSetThreadAffinity函數(shù)將所創(chuàng)建的線程固定在指定的CPU核心上運行。CPUIdleMonitorThread線程函數(shù)在執(zhí)行時先調(diào)用GetCurrentProcessorNumber函數(shù)取得執(zhí)行當前線程的CPU核,而后再利用CeGetIdleTimeEx函數(shù)最終計算出每個CPU核心的負載率。完整的例子代碼如下:
#include"stdafx.h"
// time in seconds to run the monitor thread
#defineIDLE_MONITOR_TIME 100
HANDLE g_hMonitorThreads[4];
UINT32CPUIdleMonitorThread(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]);
returnnReturn;
}
intWINAPI 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));
return0;
}
-
WINDOWS
+關注
關注
4文章
3551瀏覽量
88913 -
嵌入式主板
+關注
關注
7文章
6085瀏覽量
35440
發(fā)布評論請先 登錄
相關推薦
評論