NtQuerySystemInformation函数,其中SystemBasicInformation(0号功能)返回的结果是一个SYSTEM_BASIC_INFORMATION结构,其中的域bKeNumberProcessors将返回系统CPU的个数。 下面是该函数的具体说明: /×------------------------------------------------------------- NtQuerySystemInformation is used to check some system informations avaiable only in KernelMode (above 0x80000000). All avaiable (or all known) information classes are described in SYSTEM_INFORMATION_CLASS. Requirements Client: Requires Windows XP or Windows 2000 Professional. Server: Requires Windows 2000 Server. Header: Declared in Winternl.h. DLL: Requires Ntdll.dll. [NtQuerySystemInformation is available for use in Windows 2000 and Windows XP. It may be altered or unavailable in subsequent versions. Applications should use the alternate functions listed in this topic.] */ 注:NtQuerySystemInformation底层使用中写为ZwQuerySystemInformation,两个函数完全相同,只是入口不同。 NTSYSAPI NTSTATUS NTAPI NtQuerySystemInformation( //SystemInformationClass //[in] One of the values enumerated in SYSTEM_INFORMATION_CLASS, //indicating the kind of system information to be retrieved. IN SYSTEMINFOCLASS SystemInformationClass, // SystemInformation // [in, out] Points to a buffer where the requested information is // to be returned. The size and structure of this information varies // depending on the value of the SystemInformationClass parameter: OUT PVOID pSystemInformation, // SystemInformationLength // [in] Size of the buffer pointed to by the SystemInformation parameter, // in bytes. IN ULONG uSystemInformationLength, // ReturnLength // [out, optional] Optional pointer to a location where the function // writes the actual size of the information requested. // If that size is less than or equal to the SystemInformationLength // parameter, the function copies the information into the // SystemInformation buffer; otherwise, it returns an NTSTATUS error code // and returns in ReturnLength the size of buffer required to receive // the requested information. OUT PULONG puReturnLength OPTIONAL ); // Return Values // Returns an NTSTATUS success or error code. // The forms and significance of NTSTATUS error codes are listed // in the Ntstatus.h header file available in the Windows Device // Driver Kit (DDK), and are described in the DDK documentation // under Kernel-Mode Driver Architecture / Design Guide / Driver // Programming Techniques / Logging Errors. typedef enum _SYSTEMINFOCLASS { SystemBasicInformation, //0 SystemProcessorInformation, // 1 SystemPerformanceInformation, //2 SystemTimeOfDayInformation, //3 SystemPathInformation, //4 SystemNotImplemented1 SystemProcessInformation, //5 per process SystemProcessesAndThreadsInformation SystemCallCountInformation, //6 SystemCallInformation SystemConfigurationInformation, //7 SystemDeviceInformation SystemProcessorPerformanceInformation, //8 per cpu SystemProcessorCounters SystemGlobalFlag, //SystemFlagsInformation SystemCallTimeInformation, //10 SystemModuleInformation, //11 SystemLockInformation, //12 SystemStackTraceInformation, //13 SystemNotImplemented2 SystemPagedPoolInformation, //14 checked build only SystemNonPagedPoolInformation, //15 checked build only SystemHandleInformation, //16 SystemObjectInformation, //17 SystemObjectTypeInformation SystemPageFileInformation, //18 per page file SystemVdmInstemulInformation, //19 SystemVdmInstemulInformation SystemVdmBopInformation, //20 SystemFileCacheInformation, //21 SystemPoolTagInformation, //22 SystemInterruptInformation, //23 SystemDpcBehaviorInformation, //24 SystemFullMemoryInformation, //25 checked build only SystemLoadGdiDriverInformation, //26 set mode only SystemUnloadGdiDriverInformation, //27 set mode only SystemTimeAdjustmentInformation, //28 writeable SystemSummaryMemoryInformation, //29 checked build only SystemNextEventIdInformation, //30 checked build only SystemEventIdsInformation, //31 checked build only SystemCrashDumpInformation, //32 SystemExceptionInformation, //33 SystemCrashDumpStateInformation, //34 SystemKernelDebuggerInformation, //35 SystemContextSwitchInformation, //36 SystemRegistryQuotaInformation, //37 SystemExtendServiceTableInformation, //38 set mode only SystemAddDriver SystemPrioritySeperation, //39 set mode only SystemPrioritySeparationInformation SystemPlugPlayBusInformation, //40 not implemented SystemDockInformation, //41 not implemented SystemPowerInformation, //42 XP only SystemProcessorSpeedInformation, //43 XP only SystemCurrentTimeZoneInformation, //44 SystemLookasideInformation, //45 SystemSetTimeSlipEvent, //46 SystemCreateSession, // set mode only SystemDeleteSession, // set mode only SystemInvalidInfoClass1, // invalid info class SystemRangeStartInformation, // 0x0004 (fails if size != 4) SystemVerifierInformation, SystemAddVerifier, SystemSessionProcessesInformation, // checked build only MaxSystemInfoClass } SYSTEMINFOCLASS, *PSYSTEMINFOCLASS; typedef struct _SYSTEM_BASIC_INFORMATION { DWORD dwUnknown1; // 0 ULONG uKeMaximumIncrement; // x86: 0x0002625A or 0x00018730 ULONG uPageSize; // bytes ULONG uMmNumberOfPhysicalPages; ULONG uMmLowestPhysicalPage; ULONG uMmHighestPhysicalPage; ULONG uAllocationGranularity; // bytes PVOID pLowestUserAddress; PVOID pMmHighestUserAddress; KAFFINITY uKeActiveProcessors; BYTE bKeNumberProcessors; BYTE bUnknown2; WORD wUnknown3; } SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION; typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { LARGE_INTEGER IdleTime; LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER DpcTime; LARGE_INTEGER InterruptTime; DWORD InterruptCount; DWORD dwUnknown1; } SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION typedef struct _SYSTEM_PERFORMANCE_INFORMATION { LARGE_INTEGER liIdleTime; LARGE_INTEGER IoReadTransferCount; LARGE_INTEGER IoWriteTransferCount; LARGE_INTEGER IoOtherTransferCount; ULONG IoReadOperationCount; ULONG IoWriteOperationCount; ULONG IoOtherOperationCount; ULONG AvailablePages; ULONG CommittedPages; ULONG CommitLimit; ULONG PeakCommitment; ULONG PageFaultCount; ULONG CopyOnWriteCount; ULONG TransitionCount; ULONG CacheTransitionCount; ULONG DemandZeroCount; ULONG PageReadCount; ULONG PageReadIoCount; ULONG CacheReadCount; ULONG CacheIoCount; ULONG DirtyPagesWriteCount; ULONG DirtyWriteIoCount; ULONG MappedPagesWriteCount; ULONG MappedWriteIoCount; ULONG PagedPoolPages; ULONG NonPagedPoolPages; ULONG PagedPoolAllocs; ULONG PagedPoolFrees; ULONG NonPagedPoolAllocs; ULONG NonPagedPoolFrees; ULONG FreeSystemPtes; ULONG ResidentSystemCodePage; ULONG TotalSystemDriverPages; ULONG TotalSystemCodePages; ULONG NonPagedPoolLookasideHits; ULONG PagedPoolLookasideHits; ULONG Spare3Count; ULONG ResidentSystemCachePage; ULONG ResidentPagedPoolPage; ULONG ResidentSystemDriverPage; ULONG CcFastReadNoWait; ULONG CcFastReadWait; ULONG CcFastReadResourceMiss; ULONG CcFastReadNotPossible; ULONG CcFastMdlReadNoWait; ULONG CcFastMdlReadWait; ULONG CcFastMdlReadResourceMiss; ULONG CcFastMdlReadNotPossible; ULONG CcMapDataNoWait; ULONG CcMapDataWait; ULONG CcMapDataNoWaitMiss; ULONG CcMapDataWaitMiss; ULONG CcPinMappedDataCount; ULONG CcPinReadNoWait; ULONG CcPinReadWait; ULONG CcPinReadNoWaitMiss; ULONG CcPinReadWaitMiss; ULONG CcCopyReadNoWait; ULONG CcCopyReadWait; ULONG CcCopyReadNoWaitMiss; ULONG CcCopyReadWaitMiss; ULONG CcMdlReadNoWait; ULONG CcMdlReadWait; ULONG CcMdlReadNoWaitMiss; ULONG CcMdlReadWaitMiss; ULONG CcReadAheadIos; ULONG CcLazyWriteIos; ULONG CcLazyWritePages; ULONG CcDataFlushes; ULONG CcDataPages; ULONG ContextSwitches; ULONG FirstLevelTbFills; ULONG SecondLevelTbFills; ULONG SystemCalls; } 我们在任务管理器中所见到的所有信息只使用了下面5个调用: 0 SystemBasicInformation 2 SystemPerformanceInformation 5 SystemProcessInformation 8 SystemProcessorPerformanceInformation 21 SystemFileCacheInformation 初始化部分使用了其中的3个调用(0、2、8),这里给出的是任务管理器的初始化部分: 010058D6 InitPerfInfo proc near 010058D6 010058D6 SYSPROCPERFINFO= SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ptr -76Ch 010058D6 SYSPERFINFO= SYSTEM_PERFORMANCE_INFORMATION ptr -16Ch 010058D6 SYSBASICINFO= SYSTEM_BASIC_INFORMATION ptr -34h 010058D6 pBuf= dword ptr -8 010058D6 i = dword ptr -4 010058D6 010058D6 push ebp 010058D7 mov ebp, esp 010058D9 sub esp, 76Ch 010058DF push ebx 010058E0 push esi 010058E1 xor ebx, ebx 010058E3 push edi 010058E4 push ebx ; puReturnLength 010058E5 lea eax, [ebp+SYSBASICINFO] 010058E8 push 2Ch ; SizeOf(SYSTEM_BASIC_INFORMATION) 010058EA push eax ; pSystemInformation 010058EB push ebx ; ebx = 0 SystemBasicInformation 010058EC call ds:NtQuerySystemInformation 010058F2 cmp eax, ebx 010058F4 jl Err_CpuNumAbove32 010058FA mov eax, [ebp+SYSBASICINFO.uPageSize] 010058FD mov g_PageSize, eax ; 页面大小 01005902 mov al, [ebp+SYSBASICINFO.bKeNumberProcessors] 01005905 cmp al, 32 ; 32位Windows操作系统最多允许系统有32个CPU 01005907 mov g_cProcessors, al ; CPU的个数 0100590C ja Err_CpuNumAbove32 01005912 mov esi, ds:LocalAlloc 01005918 mov edi, 1F40h 0100591D test al, al 0100591F jbe short CpuNumEquOne 01005921 01005921 Loop_for_AllocMem: 01005921 push edi 01005922 push LMEM_ZEROINIT 01005924 call esi ; LocalAlloc 01005926 test eax, eax 01005928 mov g_pCPUHistory[ebx*4], eax 0100592F jz Err_CpuNumAbove32 01005935 push edi 01005936 push LMEM_ZEROINIT 01005938 call esi ; LocalAlloc 0100593A test eax, eax 0100593C mov g_pKernelHistory[ebx*4], eax 01005943 jz Err_CpuNumAbove32 01005949 movzx eax, g_cProcessors 01005950 inc ebx 01005951 cmp ebx, eax 01005953 jl short Loop_for_AllocMem 01005955 01005955 CpuNumEquOne: 01005955 push edi 01005956 push LMEM_ZEROINIT 01005958 call esi ; LocalAlloc 0100595A test eax, eax 0100595C mov g_pMEMHistory, eax 01005961 jz Err_CpuNumAbove32 01005967 push 0 ; puReturnLength 01005969 lea eax, [ebp+SYSPROCPERFINFO] 0100596F push 600h ; 为32个CPU准备空间 0100596F ; SizeOf(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)*32 01005974 push eax ; pSystemInformation 01005975 push SystemProcessorPerformanceInformation ; SystemInformationClass 01005977 call ds:NtQuerySystemInformation 0100597D test eax, eax 0100597F jl Err_CpuNumAbove32 01005985 movzx eax, g_cProcessors 0100598C and [ebp+i], 0 01005990 test eax, eax 01005992 jle short CpuNumEquOne_1 01005994 lea eax, [ebp+SYSPROCPERFINFO.KernelTime] 0100599A mov [ebp+pBuf], offset PreviousCPUKernelTime 010059A1 010059A1 Loop_IniCpuAllTime: 010059A1 mov ecx, [ebp+i] 010059A4 mov edx, [eax-8] ; edx = IdleTime.LowPart 010059A7 mov edi, [eax+8] ; edi = UserTime.LowPart 010059AA mov esi, [eax+4] ; esi = KernelTime.HighPart 010059AD shl ecx, 3 ; ecx = i X 8 010059B0 mov ebx, [eax+0Ch] ; ebx = UserTime.HighPart 010059B3 mov dword ptr PreviousCPUIdleTime.LowPart[ecx], edx 010059B9 mov edx, [eax-4] ; edx = IdleTime.HighPart 010059BC mov PreviousCPUIdleTime.HighPart[ecx], edx 010059C2 mov edx, [eax] ; KernelTime.LowPart 010059C4 add edi, edx ; edi = UserTime.LowPart + KernelTime.LowPart 010059C6 adc ebx, esi ; 带进位加 010059C6 ; ebx = UserTime.HighPart + KernelTime.HighPart 010059C8 add edx, [eax-8] ; edx = KernelTime.LowPart + IdleTime.LowPart 010059CB mov dword ptr PreviousCPUTotalTime.LowPart[ecx], edi 010059D1 mov PreviousCPUTotalTime.HighPart[ecx], ebx 010059D7 mov ecx, [ebp+pBuf] ; PreviousCPUKernelTime的指针 010059DA adc esi, [eax-4] ; 带进位加 010059DA ; esi = KernelTime.HighPart + IdleTime.HighPart 010059DD add eax, 30h ; 取下一个CPU的相关数据 010059DD ; SizeOf(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) 010059E0 inc [ebp+i] 010059E3 mov [ecx], edx ; PreviousCPUTotalTime.LowPart = KernelTime.LowPart + IdleTime.LowPart 010059E5 mov [ecx+4], esi ; PreviousCPUTotalTime.HighPart = KernelTime.HighPart + IdleTime.HighPart 010059E8 add ecx, 8 ; 移动PreviousCPUKernelTime的指针 010059EB mov [ebp+pBuf], ecx ; 保存PreviousCPUKernelTime的指针 010059EE movzx ecx, g_cProcessors 010059F5 cmp [ebp+i], ecx ; 和Cpu的个数比较 010059F8 jl short Loop_IniCpuAllTime 010059FA 010059FA CpuNumEquOne_1: ; puReturnLength 010059FA push 0 010059FC lea eax, [ebp+SYSPERFINFO] 01005A02 push 138h ; SizeOf(SYSTEM_PERFORMANCE_INFORMATION) 01005A07 push eax ; pSystemInformation 01005A08 push SystemPerformanceInformation ; SystemInformationClass 01005A0A call ds:NtQuerySystemInformation 01005A10 test eax, eax 01005A12 jge short Init_Exit 01005A14 01005A14 Err_CpuNumAbove32: ; 如果出错返回 0 01005A14 xor al, al 01005A16 jmp short Exit 01005A18 01005A18 Init_Exit: 01005A18 mov eax, g_PageSize 01005A1D shr eax, 10 01005A20 imul eax, [ebp+SYSPERFINFO.CommitLimit] 01005A27 mov g_MEMMax, eax 01005A2C mov al, g_cProcessors ; 返回Cpu的个数 01005A31 01005A31 Exit: 01005A31 pop edi 01005A32 pop esi 01005A33 pop ebx 01005A34 leave 01005A35 retn 01005A35 InitPerfInfo endp 01005A35 NtQuerySystemInformation非常复杂,其中的结构随着Windows的版本变化会发生变化,这里给出的结构是2K系统的。