我想要做的是编写一个连续生活的小程序来计算特定进程在足够小的时间单元内所经历的上下文切换次数。 我在软件“Process Explorer”中观察到了这个function,所以我知道这是绝对有可能的。
不幸的是,我对如何开始编码这个问题一无所知,到目前为止还找不到任何有用的代码片断。 因此,实现每个进程和每单位时间的活动上下文切换计数的小实例将对我非常有帮助。
这里有一种方法 – 这将打印记事本的线程0使用的上下文切换的数量(您可以在CounterPathBuffer初始化中替换您想要的任何进程和线程数)每秒:
#include "stdafx.h" #include <iostream> #include <windows.h> #include <stdio.h> #include <conio.h> #include <pdh.h> #include <pdhmsg.h> #pragma comment(lib, "pdh.lib") using namespace std; CONST ULONG SAMPLE_INTERVAL_MS = 1000; CONST PWSTR BROWSE_DIALOG_CAPTION = L"Select a counter to monitor."; void wmain(void) { PDH_STATUS Status; HQUERY Query = NULL; HCOUNTER Counter; PDH_FMT_COUNTERVALUE DisplayValue; DWORD CounterType; SYSTEMTIME SampleTime; PDH_BROWSE_DLG_CONFIG BrowseDlgData; WCHAR CounterPathBuffer[PDH_MAX_COUNTER_PATH] = L"\\\\ComputerNameGoesHere\\Thread(notepad/0)\\Context Switches/sec"; // // Create a query. // Status = PdhOpenQuery(NULL, NULL, &Query); if (Status != ERROR_SUCCESS) { wprintf(L"\nPdhOpenQuery failed with status 0x%x.", Status); goto Cleanup; } // // Initialize the browser dialog window settings. // ZeroMemory(&BrowseDlgData, sizeof(PDH_BROWSE_DLG_CONFIG)); BrowseDlgData.bIncludeInstanceIndex = FALSE; BrowseDlgData.bSingleCounterPerAdd = TRUE; BrowseDlgData.bSingleCounterPerDialog = TRUE; BrowseDlgData.bLocalCountersOnly = FALSE; BrowseDlgData.bWildCardInstances = TRUE; BrowseDlgData.bHideDetailBox = TRUE; BrowseDlgData.bInitializePath = FALSE; BrowseDlgData.bDisableMachineSelection = FALSE; BrowseDlgData.bIncludeCostlyObjects = FALSE; BrowseDlgData.bShowObjectBrowser = FALSE; BrowseDlgData.hWndOwner = NULL; BrowseDlgData.szReturnPathBuffer = CounterPathBuffer; BrowseDlgData.cchReturnPathLength = PDH_MAX_COUNTER_PATH; BrowseDlgData.pCallBack = NULL; BrowseDlgData.dwCallBackArg = 0; BrowseDlgData.CallBackStatus = ERROR_SUCCESS; BrowseDlgData.dwDefaultDetailLevel = PERF_DETAIL_WIZARD; BrowseDlgData.szDialogBoxCaption = BROWSE_DIALOG_CAPTION; // // Add the selected counter to the query. // Status = PdhAddCounter(Query, CounterPathBuffer, 0, &Counter); if (Status != ERROR_SUCCESS) { wprintf(L"\nPdhAddCounter failed with status 0x%x.", Status); goto Cleanup; } // // Most counters require two sample values to display a formatted value. // PDH stores the current sample value and the previously collected // sample value. This call retrieves the first value that will be used // by PdhGetFormattedCounterValue in the first iteration of the loop // Note that this value is lost if the counter does not require two // values to compute a displayable value. // Status = PdhCollectQueryData(Query); if (Status != ERROR_SUCCESS) { wprintf(L"\nPdhCollectQueryData failed with 0x%x.\n", Status); goto Cleanup; } // // Print counter values until a key is pressed. // while (!_kbhit()) { Sleep(SAMPLE_INTERVAL_MS); GetLocalTime(&SampleTime); Status = PdhCollectQueryData(Query); if (Status != ERROR_SUCCESS) { wprintf(L"\nPdhCollectQueryData failed with status 0x%x.", Status); } wprintf(L"\n\"%2.2d/%2.2d/%4.4d %2.2d:%2.2d:%2.2d.%3.3d\"", SampleTime.wMonth, SampleTime.wDay, SampleTime.wYear, SampleTime.wHour, SampleTime.wMinute, SampleTime.wSecond, SampleTime.wMilliseconds); // // Compute a displayable value for the counter. // Status = PdhGetFormattedCounterValue(Counter, PDH_FMT_DOUBLE, &CounterType, &DisplayValue); if (Status != ERROR_SUCCESS) { wprintf(L"\nPdhGetFormattedCounterValue failed with status 0x%x.", Status); goto Cleanup; } wprintf(L",\"%.20g\"", DisplayValue.doubleValue); } Cleanup: // // Close the query. // if (Query) { PdhCloseQuery(Query); } int x; cin >>x; }
大部分的代码是从这个来源: msdn.microsoft.com/en-us/library/aa371886%28v=vs.85%29.aspx 。 我想缩短上下文切换连续检查之间的时间(使其小于一秒)。 如果任何人有任何想法如何做到这一点,这将是伟大的。
在互联网上搜索一下,我发现了一个名为“ 性能计数器 ”的东西,你可以提供计数器数据或者消耗计数器数据。 在你的情况下,我相信你想从性能计数器读取数据。
您可以使用注册表接口或PDH接口来使用性能数据。 PDH界面比注册表界面更易于使用,建议用于大多数性能数据收集任务。 PDH接口本质上是注册表接口提供的功能的更高级抽象。
这是另一篇来自Microsoft的关于Monitoring Context Switches的文章 。
如果需要,ETW(Windows事件跟踪)将为您提供有关上下文切换的更深层次的信息。 代码可能比访问性能计数器复杂得多。
初始链接: Windows 7中的核心操作系统事件和Windows性能工具包技术参考
搜索术语:“ETW上下文切换”,“xperf”