ntdllのNtQuerySystemInformationを使用して、各プロセッサの性能に関する情報を得たいと考えています。今私はそれがちょうど5つすべての試行を実行し、その後返すという問題があります。c# - 構造体の配列のポインタの問題
NtQuerySystemInformationは常にInfoLengthMismatchであるNtStatusを返します。通常、これは通常、自分のバッファを大きくする必要があることを意味します。 1つのプロセッサ(配列なし)と0x10000のバッファサイズで試してみると、ちょっとうまく動作しますが、最初のtryではInfoLengthMismatchが得られますが、2回目は常に動作します。
私はバッファを100倍も増加させようとしましたが、何も効果がありませんでした。
private _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[] GetPerformanceInfo()
{
try
{
//Getting count of processors
SYSTEM_INFO sysInfo = new SYSTEM_INFO();
GetSystemInfo(out sysInfo);
int processors = (int)sysInfo.numberOfProcessors;
int tries = 0;
while (true)
{
//buffer size
uint infoLength = (uint)(Marshal.SizeOf(typeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)) * processors);
//buffer
IntPtr infoPtr = Marshal.AllocHGlobal((int)infoLength);
//Problem: result is always InfoLengthMismatch
NtStatus result = NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS.SystemProcessorPerformanceInformation, infoPtr, infoLength, out infoLength);
//if success, get the array and return it
if (result == NtStatus.Success)
{
int szStruct = Marshal.SizeOf(typeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[] localStructs = new _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[processors];
for (uint i = 0; i < processors; i++)
localStructs[i] = (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)Marshal.PtrToStructure(new IntPtr(infoPtr.ToInt64() + (szStruct * processors)), typeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
return localStructs;
}
//free ptr when fail
Marshal.FreeHGlobal(infoPtr);
if (++tries > 5)
return null;
//set ptr again, new try
infoPtr = Marshal.AllocHGlobal((int)infoLength);
}
}
catch (Exception e)
{
Console.WriteLine(e.Source + ": " + e.Message.ToString());
return null;
}
}
}
//struct of a large int
[StructLayout(LayoutKind.Explicit, Size = 8)]
public struct LARGE_INTEGER
{
[FieldOffset(0)] public Int64 QuadPart;
[FieldOffset(0)] public UInt32 LowPart;
[FieldOffset(4)] public Int32 HighPart;
}
//struct
public struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
{
public LARGE_INTEGER IdleTime;
public LARGE_INTEGER KernelTime;
public LARGE_INTEGER UserTime;
public LARGE_INTEGER Reserved1;
public ulong Reserved2;
}
EDIT:サイズが間違っている
uint infoLength = (uint)(Marshal.SizeOf(typeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)) * processors);
通常ならば、それは、この場合には、私はinfoLengthのVARに適切なサイズに設定していてます:間違った事は、このラインでしたそれはループの始めに毎回です。
メモリを2回割り当てて1回解放することは承知していますか? – Enfyve