作者:SkyJacker
(轉貼請保持完整並註明作者和出處)
http://www.cnpack.org
CnPack IV QQ Group: 130970
2007-01-23
感謝:Passion,Bahamut,早安,空氣,SkyJacker...
沒有Bahamut的奇思妙點,就沒有這片文章。
在多cpu、多核中,會隨機的獲得不同的序列號.這就爲我們根據cpu序列號來製作註冊機帶來了很大的麻煩。
Windows 2000/xp允許設置進程和線程的親緣性。換句話說,可以控制哪個 CPU 能夠運行某些線程。這稱爲硬親緣性。Windows提供了設置親緣性的函數SetProcessAffinityMask 。使用它可控制獲取指定cpu的序列號。
本文分爲2部分:
1、如何獲得cpu的序列號。
2、如何獲取指定cpu或指定cpu核的序列號。
1、如何獲得cpu的序列號。
使用cpuid指令來獲取。
在調用CPUID之前,EAX中存放的是功能代碼。在調用CPUID之後,EAX,EBX,ECX,EDX存放的是CPU的各種特徵信息。這些信息也就是我們通常所說的CPU序列號。
mov eax, 0 //獲取製造商信息
cpuid
mov eax, 1 //獲得CPU的序列號
cpuid
以下三個函數,可供參考:
function NewCPUID: string;
const
CPUINFO = 'CPU製造商: %S 序列號: %x';
var
s: array[0..19] of Char;
MyCpuID: Integer;
begin
FillChar(s, 20, 0);
asm
push ebx
push ecx
push edx
mov eax, 0
cpuid
mov dword ptr s[0], ebx
mov dword ptr s[4], edx
mov dword ptr s[8], ecx
mov eax, 1
cpuid
mov MyCpuID, edx
pop edx
pop ecx
pop ebx
end;
Result := Format(CPUINFO, [s, MyCpuID]);
end;
function GetCPUID: TCPUID; assembler; register;
asm
PUSH EBX {Save affected register}
PUSH EDI
MOV EDI, EAX [email={@Resukt]{@Resukt[/email]}
MOV EAX, 1
DW $A20F {CPUID Command}
STOSD {CPUID[1]}
MOV EAX, EBX
STOSD {CPUID[2]}
MOV EAX, ECX
STOSD {CPUID[3]}
MOV EAX, EDX
STOSD {CPUID[4]}
POP EDI {Restore registers}
POP EBX
end;
//獲取cpu的序列號:
function GetCnCPUID(): string;
const
CPUINFO = '%.8x-%.8x-%.8x-%.8x';
var
iEax: Integer;
iEbx: Integer;
iEcx: Integer;
iEdx: Integer;
begin
asm
push ebx
push ecx
push edx
mov eax, 1
DW $A20F//cpuid
mov iEax, eax
mov iEbx, ebx
mov iEcx, ecx
mov iEdx, edx
pop edx
pop ecx
pop ebx
end;
Result := Format(CPUINFO, [iEax, iEbx, iEcx, iEdx]);
end;
2、如何獲取指定cpu或指定cpu核的序列號。
根據Windows可以設置進程和線程的親緣性的特點,使用SetProcessAffinityMask函數,來控制哪個cpu來運行獲取序列號的進程,因此也就獲取了指定的cpu的序列號。爲了和單cpu兼容,建議總是獲取第一個cpu的序列號。
procedure SetCPU(h: THandle;CpuNo: Integer);
//CpuNo:決定了獲得第幾個cpu內核的第幾個序列號。
var
ProcessAffinity: Cardinal;
_SystemAffinity: Cardinal;
begin
GetProcessAffinityMask(h, ProcessAffinity, _SystemAffinity) ;
ProcessAffinity := CpuNo; //this sets the process to only run on CPU 0
//for CPU 1 only use 2 and for CPUs 1 & 2 use 3
SetProcessAffinityMask(h, ProcessAffinity)
end;
使用方法:
SetCPU(GetCurrentProcess,1); //第一個cpu的第一個cpu內核
ShowMessage(GetCnCPUID);
後記:這片文章源於CnPack 羣裏關於獲取多核CPU的ID的問題討論。
感謝CnPack 羣裏的所有成員。
BS下'早安空氣',竟然說“你在你短暫的生命裏花大量的時間去做這個沒有價值的事情”-_-!!超級BS、BS、BS……^_^
for I:=0 to 10000000000000000000000000000 do
BS;
附錄“早安空氣”語錄:
'放棄吧,API不適合你'
'你在你短暫的生命裏花大量的時間去做這個沒有價值的事情'