2011-08-07 20 views
6

GetLogicalProcessorInformation işlevini kullanarak C#/PInvoke işlevini çağırmak istiyorum, ancak SYSTEM_LOGICAL_PROCESSOR_INFORMATION struct ve CACHE_DESCRIPTOR yapısına yapıştım.GetLogicalProcessorInformation Fonksiyonu için PInvoke

Bu yapıları doğru kullanım için nasıl tanımlamalıyım?

Ana problemler:
1. SYSTEM_LOGICAL_PROCESSOR_INFORMATION tanımı
3. CACHE_DESCRIPTOR sahiptir WORD ve tanımı DWORD kendi tanımı
2. SYSTEM_LOGICAL_PROCESSOR_INFORMATION sahiptir ULONGLONG birlik sahiptir.

Bu yapılarda bana yardımcı olabilir misiniz?

+0

Reddetme nedenlerinden herhangi biri mi var? – VMAtm

cevap

10

Güncelleme: elle yapılmalıdır yapı sıralanırken sabit.

Bu oldukça dağınık bir P/invoke. Yapıları ve birleşimi tanımladığınız zaman bile, işlevi çağırmak önemsizdir çünkü yapıları el ile sıralamak zorundasınız.

[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. – Dennis

+0

Aşağıdaki derleme hatası var (.NET 1.1 üzerinde) 'Operator' + = ',' System.IntPtr 've' int 'türünde işlenenlere uygulanamaz. IntPtr yerine int * 'kullanabilir miyim? – VMAtm

+0

Aşağıdakileri kullanmayı denedim: 'Item = new IntPtr (Item.ToInt32() + size);' ve çalıştı. 'Int *' yi kullanabilirsem söylerim. – VMAtm

4

A DWORDuint ve WORDushort'dur. Bir union

[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, 
} 

bir Explicit düzeni ve FieldOffset bir yapıdır.

[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, 
} 

bir ULONGLONG bir UInt64 olup. Yapının 8 bayt sınırına (24 bayt) hizalanmasıdır. David'in yorumlarda belirttiği gibi, bazı nedenlerden dolayı Microsoft Interop kütüphanesinden eksikti.

Güncelleştirme: Microsoft Research'ten Windows Interop Kütüphanesi'ne eksik yapılar ve bağlantı eklendi.

Kaynak: WindowsInteropLib/Kernel32.cs

+1

Bu cevap bütün bu çekicilikleri cezbediyor olsa da, iki önemli şekilde ciddi olarak eksik olduğum görülüyor. 'ULONGLONG [2] Ayrılmış' üyesini görmezden gelerek, yapının doğru boyutta olduğunu, doğru 24 bayt yerine 20 bayt olduğunu belirtir. Ve daha da önemlisi, aslında doğru olması oldukça zor olan işlevi çağırmaktan söz edilmez. –

+2

Bunu işaret ettiğin için teşekkürler David - Sadece cevabını okuyordum ve aynı şeyi farkettim. Daha eksiksiz cevap için – Dennis