2011-08-07 10 views
6

Chcę wywołać za pomocą C#/PInvoke funkcji GetLogicalProcessorInformation, ale utknąłem w strukturze SYSTEM_LOGICAL_PROCESSOR_INFORMATION struct i CACHE_DESCRIPTOR.Wywołanie funkcji GetLogicalProcessorInformation

Jak zdefiniować te elementy dla prawidłowego użytkowania?

Główne problemy:
1. SYSTEM_LOGICAL_PROCESSOR_INFORMATION ma związek z jego definicji
2. SYSTEM_LOGICAL_PROCESSOR_INFORMATION ma ULONGLONG w swojej definicji
3. CACHE_DESCRIPTOR ma WORD i DWORD w jego definicji.

Czy możesz mi pomóc w tych strukturach?

+0

Jakieś powody do przegłosowania? – VMAtm

Odpowiedz

10

Updated: stała się rozrządowych struktury, które ma być wykonane ręcznie.

To dość nieprzyjemne P/wywołanie. Nawet jeśli zdefiniowane są struktury i unia, wywołanie funkcji jest nietrywialne, ponieważ trzeba ręcznie zarządzać strukturami.

[StructLayout(LayoutKind.Sequential)] 
public struct PROCESSORCORE 
{ 
    public byte Flags; 
}; 

[StructLayout(LayoutKind.Sequential)] 
public struct NUMANODE 
{ 
    public uint NodeNumber; 
} 

public enum PROCESSOR_CACHE_TYPE 
{ 
    CacheUnified, 
    CacheInstruction, 
    CacheData, 
    CacheTrace 
} 

[StructLayout(LayoutKind.Sequential)] 
public struct CACHE_DESCRIPTOR 
{ 
    public byte Level; 
    public byte Associativity; 
    public ushort LineSize; 
    public uint Size; 
    public PROCESSOR_CACHE_TYPE Type; 
} 

[StructLayout(LayoutKind.Explicit)] 
public struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION_UNION 
{ 
    [FieldOffset(0)] 
    public PROCESSORCORE ProcessorCore; 
    [FieldOffset(0)] 
    public NUMANODE NumaNode; 
    [FieldOffset(0)] 
    public CACHE_DESCRIPTOR Cache; 
    [FieldOffset(0)] 
    private UInt64 Reserved1; 
    [FieldOffset(8)] 
    private UInt64 Reserved2; 
} 

public enum LOGICAL_PROCESSOR_RELATIONSHIP 
{ 
    RelationProcessorCore, 
    RelationNumaNode, 
    RelationCache, 
    RelationProcessorPackage, 
    RelationGroup, 
    RelationAll = 0xffff 
} 

public struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION 
{ 
    public UIntPtr ProcessorMask; 
    public LOGICAL_PROCESSOR_RELATIONSHIP Relationship; 
    public SYSTEM_LOGICAL_PROCESSOR_INFORMATION_UNION ProcessorInformation; 
} 

[DllImport(@"kernel32.dll", SetLastError=true)] 
public static extern bool GetLogicalProcessorInformation(
    IntPtr Buffer, 
    ref uint ReturnLength 
); 

private const int ERROR_INSUFFICIENT_BUFFER = 122; 

public static SYSTEM_LOGICAL_PROCESSOR_INFORMATION[] MyGetLogicalProcessorInformation() 
{ 
    uint ReturnLength = 0; 
    GetLogicalProcessorInformation(IntPtr.Zero, ref ReturnLength); 
    if (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER) 
    { 
     IntPtr Ptr = Marshal.AllocHGlobal((int)ReturnLength); 
     try 
     { 
      if (GetLogicalProcessorInformation(Ptr, ref ReturnLength)) 
      { 
       int size = Marshal.SizeOf(typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); 
       int len = (int)ReturnLength/size; 
       SYSTEM_LOGICAL_PROCESSOR_INFORMATION[] Buffer = new SYSTEM_LOGICAL_PROCESSOR_INFORMATION[len]; 
       IntPtr Item = Ptr; 
       for (int i = 0; i < len; i++) 
       { 
        Buffer[i] = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION)Marshal.PtrToStructure(Item, typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); 
        Item += size; 
       } 
       return Buffer; 
      } 
     } 
     finally 
     { 
      Marshal.FreeHGlobal(Ptr); 
     } 
    } 
    return null; 
} 

static void Main(string[] args) 
{ 
    SYSTEM_LOGICAL_PROCESSOR_INFORMATION[] Buffer = MyGetLogicalProcessorInformation(); 
    for (int i=0; i<Buffer.Length; i++) 
    { 
     Console.WriteLine(Buffer[i].ProcessorMask); 
    } 
} 
+1

+1, aby uzyskać pełniejszą odpowiedź. – Dennis

+0

Mam następujący błąd kompilacji (na .NET 1.1) 'Operator '+ =" nie można zastosować do operandów typu "System.IntPtr" i "int''. Czy mogę użyć 'int *' zamiast IntPtr? – VMAtm

+0

Próbowałem użyć następującego: 'Item = new IntPtr (Item.ToInt32() + size);' i zadziałało. Powiem, jeśli mogę użyć 'int *'. – VMAtm

4

A DWORD to uint i WORD to ushort.

[StructLayout(LayoutKind.Sequential)] 
struct CACHE_DESCRIPTOR 
{ 
    public byte Level; 
    public byte Associativity; 
    public ushort LineSize; 
    public uint Size; 
    public PROCESSOR_CACHE_TYPE Type; 
} 

enum PROCESSOR_CACHE_TYPE 
{ 
    Unified = 0, 
    Instruction = 1, 
    Data = 2, 
    Trace = 3, 
} 

union jest strukturą o Explicit układu i FieldOffset.

[StructLayout(LayoutKind.Sequential)] 
struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION 
{ 
    public UIntPtr ProcessorMask; 
    public LOGICAL_PROCESSOR_RELATIONSHIP Relationship; 
    public ProcessorRelationUnion RelationUnion; 
} 

[StructLayout(LayoutKind.Explicit)] 
struct ProcessorRelationUnion 
{ 
    [FieldOffset(0)] public CACHE_DESCRIPTOR Cache; 
    [FieldOffset(0)] public uint NumaNodeNumber; 
    [FieldOffset(0)] public byte ProcessorCoreFlags; 
    [FieldOffset(0)] private UInt64 Reserved1; 
    [FieldOffset(8)] private UInt64 Reserved2; 
} 

[StructLayout(LayoutKind.Sequential)] 
struct CACHE_DESCRIPTOR 
{ 
    public byte Level; 
    public byte Associativity; 
    public ushort LineSize; 
    public uint Size; 
    public PROCESSOR_CACHE_TYPE Type; 
} 

enum LOGICAL_PROCESSOR_RELATIONSHIP : uint 
{ 
    ProcessorCore = 0, 
    NumaNode = 1, 
    RelationCache = 2, 
} 

ULONGLONG jest UInt64. Chodzi o wyrównanie struktury do granicy 8 bajtów (24 bajty). Jak zauważył David w komentarzach, jest to wymagane iz jakiegoś powodu brakowało go w bibliotece Microsoft Interop.

Aktualizacja: Dodano brakujące struktury i łącze do biblioteki Interop Windows z Microsoft Research.

Źródło: WindowsInteropLib/Kernel32.cs

+1

Chociaż ta odpowiedź przyciąga wszystkie przeboje, wydaje mi się, że mam poważny niedobór na dwa ważne sposoby. Zignorowanie elementu 'ULONGLONG [2] Reserved' oznacza, że ​​struktura ma niepoprawny rozmiar, wynoszący 20 bajtów zamiast poprawnych 24 bajtów. A co ważniejsze, nie ma wzmianki o tym, że wywołanie funkcji jest dość trudne, aby uzyskać właściwą. –

+2

Dzięki za wskazanie, że David - właśnie czytałem twoją odpowiedź i uświadomiłem sobie to samo. – Dennis