2011-08-07 33 views
6

Tôi muốn gọi qua C#/PInvoke các GetLogicalProcessorInformation chức năng, nhưng tôi bị mắc kẹt với SYSTEM_LOGICAL_PROCESSOR_INFORMATION struct và CACHE_DESCRIPTOR struct.PInvoke cho GetLogicalProcessorInformation Chức năng

Tôi nên xác định các cấu trúc này để sử dụng chính xác như thế nào?

vấn đề chính:
1. SYSTEM_LOGICAL_PROCESSOR_INFORMATION có công đoàn trong định nghĩa của nó
2. SYSTEM_LOGICAL_PROCESSOR_INFORMATIONULONGLONG trong định nghĩa của nó
3. CACHE_DESCRIPTORWORDDWORD trong định nghĩa của nó.

Bạn có thể giúp tôi với những cấu trúc này không?

+0

Bất kỳ lý do gì để ghi đè? – VMAtm

Trả lời

10

Cập nhật: cố định marshalling cấu trúc mà phải được thực hiện bằng tay.

Đây là một P/gọi khá lộn xộn. Ngay cả khi bạn có các cấu trúc và liên minh được xác định, nó không tầm thường để gọi hàm bởi vì bạn phải sắp xếp các cấu trúc theo cách thủ công.

[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 để có câu trả lời hoàn chỉnh hơn. – Dennis

+0

Tôi đã có lỗi biên dịch sau (trên .NET 1.1) 'Toán tử '+ =' không thể áp dụng cho các toán hạng kiểu 'System.IntPtr' và 'int''. Tôi có thể sử dụng 'int *' thay cho IntPtr không? – VMAtm

+0

Tôi đã cố gắng sử dụng như sau: 'Item = new IntPtr (Item.ToInt32() + size);' và nó đã hoạt động. Tôi sẽ nói, nếu tôi có thể sử dụng 'int *'. – VMAtm

4

A DWORDuintWORDushort.

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

Một union là một cấu trúc với một bố trí ExplicitFieldOffset.

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

A ULONGLONGUInt64. Nó đang được sắp xếp cấu trúc đến 8 byte ranh giới (24 byte). Như David đã chỉ ra trong các bình luận, nó là bắt buộc và vì một lý do nào đó nó bị thiếu trong thư viện Microsoft Interop.

Cập nhật: Thêm cấu trúc bị thiếu và liên kết đến Thư viện tương tác Windows từ Microsoft Research.

Nguồn: WindowsInteropLib/Kernel32.cs

+1

Mặc dù câu trả lời này đang thu hút tất cả các upvotes, nó xuất hiện với tôi để được nghiêm túc thiếu trong hai cách quan trọng. Bỏ qua thành viên 'ULONGLONG [2] Reserved' có nghĩa là cấu trúc không đúng kích cỡ, là 20 byte thay vì 24 byte chính xác. Và quan trọng hơn là không có đề cập đến thực sự gọi chức năng đó là khá khó khăn để có được quyền. –

+2

Cảm ơn bạn đã chỉ ra rằng David - Tôi vừa đọc câu trả lời của bạn và nhận ra điều tương tự. – Dennis