PS! The following example code is not very clean. I know there are
several things that can be optimized but I think I call the
NtQuerySystemInformation() as I should.
CHAR cpuusage2()
{
#define SystemProcessorPerformanceInformation 0x8
static (_stdcall *ntquerysysteminformation) (int
SystemInformationClass, PVOID SystemInformation, ULONG
SystemInformationLength, PULONG ReturnLength) = 0;
SYSTEM_INFO sysinf;
unsigned long returnlength=0;
int status=0;
#pragma pack(push,8)
typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
{
LARGE_INTEGER IdleTime;
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER Reserved1[2];
ULONG Reserved2;
} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
#pragma pack(pop)
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION spi[32];
memset(spi,0,sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)*32);
if(!ntquerysysteminformation)
{
printf("*** Loading NtQuerySystemInformation\n");
ntquerysysteminformation =
GetProcAddress(LoadLibrary("ntdll.dll"),"NtQuerySystemInformation");
if(!ntquerysysteminformation)
{
printf("***ERROR: Can't link with NtQuerySystemInformation()
\n");
exit(5);
}
printf("*** Loading NtQuerySystemInformation success\n");
sleep(1500);
}
GetSystemInfo(&sysinf);
printf("Number of processors: %d\n",sysinf.dwNumberOfProcessors);
status=ntquerysysteminformation(SystemProcessorPerformanceInformation,spi,
(sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)*sysinf.dwNumberOfProcessors),&returnlength);
printf("*** ntquerysysteminformation results = %d %s
\n",status,status?"FAILED":"OK");
if(0 != status)
printf("*** ntquerysysteminformation failed (%d)\n",status);
printf("ReturnLen = %d\n",returnlength);
printf("sizeli = %d\n",sizeof(LARGE_INTEGER));
printf("structsize = %d
\n",sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
printf("CPUs (rlen) = %d\n",returnlength /
sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
if((returnlength %
sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)) !=0)
printf("*** Returned unexpected size\n");
printf("----\n");
for(int c=0;c<sysinf.dwNumberOfProcessors;c++)
{
unsigned char usage=0;
ULARGE_INTEGER ul_sys_idle;
ULARGE_INTEGER ul_sys_kernel;
ULARGE_INTEGER ul_sys_user;
static ULARGE_INTEGER ul_sys_idle_old[32];
static ULARGE_INTEGER ul_sys_kernel_old[32];
static ULARGE_INTEGER ul_sys_user_old[32];
ul_sys_idle.QuadPart = spi[c].IdleTime.QuadPart;
ul_sys_kernel.QuadPart = spi[c].KernelTime.QuadPart;
ul_sys_user.QuadPart = spi[c].UserTime.QuadPart;
usage =
(
(
(
(
(ul_sys_kernel.QuadPart - ul_sys_kernel_old[c].QuadPart)
+
(ul_sys_user.QuadPart - ul_sys_user_old[c].QuadPart)
)
-
(ul_sys_idle.QuadPart - ul_sys_idle_old[c].QuadPart)
)
*
(100)
)
/ 1+
(
(ul_sys_kernel.QuadPart - ul_sys_kernel_old[c].QuadPart)
+
(ul_sys_user.QuadPart - ul_sys_user_old[c].QuadPart)
)
);
ul_sys_idle_old[c].QuadPart = ul_sys_idle.QuadPart;
ul_sys_user_old[c].QuadPart = ul_sys_user.QuadPart;
ul_sys_kernel_old[c].QuadPart = ul_sys_kernel.QuadPart;
printf("CPU : %u\n",c);
printf("Usage : %d%%\n",usage);
printf("-\n");
printf("IdleTime = %u\n",spi[c].IdleTime.QuadPart);
printf("KernelTime = %u\n",spi[c].KernelTime.QuadPart);
printf("UserTime = %u\n",spi[c].UserTime.QuadPart);
printf("\n");
}
return 0;
}
All help appreciated - thanks in advance ;)
Hi,
I gather you want to determine the CPU load of each process,
in this case, try to use the API GetProcessTimes() in a loop, and
compare the user and the kernel times with the time passed by
using the API GetTickCount(), this approach should report the
time that your process is using on the machine.
http://msdn2.microsoft.com/en-us/library/ms683223.aspx
http://msdn2.microsoft.com/en-us/library/ms724408.aspx
Kellie.
Thanks Kellie but this was actually not what I was looking for (might
be useful tough). What I'm trying to do is to get total CPU usage or
perhaps I should say the total CPU load for each CPU in the system.
Usage is wrong.
It must be something like this :
usage = (BYTE) (100 - (((ul_sys_idle.QuadPart -
ul_sys_idle_old[c].QuadPart) * 100) /
((ul_sys_kernel.QuadPart + ul_sys_user.QuadPart) -
(ul_sys_kernel_old[c].QuadPart + ul_sys_user_old[c].QuadPart))));
(and in your case, it will be wrong the first time as old variables
are null)
BTW, the structure definition is :
typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
{
LARGE_INTEGER IdleTime;
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER DpcTime;
LARGE_INTEGER InterruptTime;
ULONG InterruptCount;
} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION,
*PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
(with a similar code in a timer, I get same results than Perf Meter or
Task Manager on 4 or 8 processors)
Hi Christian and thanks for the new info (from where is this? MSDN
have another definition of the structure). However this does not solve
my problem. I still get a returnlength of 48 and the structure is
still 44 bytes. I expect to get 88 since I have two processors but so
far no luck :( Thanks anyway
> Hi Christian and thanks for the new info (from where is this? MSDN
> have another definition of the structure). However this does not solve
> my problem. I still get a returnlength of 48 and the structure is
> still 44 bytes. I expect to get 88 since I have two processors but so
> far no luck :(
It's from ntexapi.h, which is on many sites like :
https://forum.eviloctal.com/simple/index.php?t5087.html
and
int n = sizeof SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
=> I get n = 48...
Well replacing the ULONG with a ULARGE_INTEGER in the structure did
the trick. A dirty trick by all means but it works ;) - Now the
interesting part will be to see how many systems it actually works
on ;)
Thanks for your help Christian!