如何獲取多核、多cpu系統中指定cpu的序列號

如何獲取多核、多cpu系統中指定cpu的序列號
作者: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不適合你'
'你在你短暫的生命裏花大量的時間去做這個沒有價值的事情'

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章