作者 主題: 如何用C語言取得硬體資訊,如主機板序號等?  (閱讀 16475 次)

0 會員 與 1 訪客 正在閱讀本文。

ebyaya

  • 可愛的小學生
  • *
  • 文章數: 18
    • 檢視個人資料
請教各位大大,如何用C語言取得機器的硬體資訊,如主機板序號、硬碟序號、CPU的ID等,
不知是否有範例可以參考,我的環境是CentOS 5.2,gcc-4.1.2-42

elleryq

  • 區域板主
  • 鑽研的研究生
  • *****
  • 文章數: 908
  • 性別: 男
    • 檢視個人資料
    • Thinking more...
主機板序號,可以用 dmidecode 試試看
CPU id 可以用 cat /proc/cpuinfo 看看
硬碟序號,或許可以用 smartctl 或 hdparm 取得...

dmidecode, smartctl, hdparm 都是指令,要安裝 rpm 以後,才能使用。
至於這些指令怎麼取得,就可以挖他們的 source code 來看看。
Plan your work, then work your plan.
我的首頁:http://blog.elleryq.idv.tw
351899by http://counter.li.org

ebyaya

  • 可愛的小學生
  • *
  • 文章數: 18
    • 檢視個人資料
多謝大大的回應,這個問題我找好久,上網爬文都只有Delphi和C#的文章,就是沒有C的文章,
難道C沒有自帶的函數可以解決嗎?

CPU ID /proc/cpuinfo 這我查過了裡面是沒有CPU的序號的
hdparm -i (smartctl -i)倒是可以讀取硬碟序號,不過這還是沒辦法由自行開發的程式來解決

不過dmidecode倒是給了我一線生機,他可以取得到cpu的id,不過他取主機板序號時(baseboard),
還是取不出來,呈現 xxxxxxxxx 不然就是空白,看來要用C取個主機板序號還真難 ;D

darkranger

  • 榮譽學長
  • 俺是博士!
  • *****
  • 文章數: 1382
    • 檢視個人資料
    • https://darkranger.no-ip.org
請參考 lshw 的原始碼

elleryq

  • 區域板主
  • 鑽研的研究生
  • *****
  • 文章數: 908
  • 性別: 男
    • 檢視個人資料
    • Thinking more...
長見識
學到了
thanks.
Plan your work, then work your plan.
我的首頁:http://blog.elleryq.idv.tw
351899by http://counter.li.org

ebyaya

  • 可愛的小學生
  • *
  • 文章數: 18
    • 檢視個人資料
經過我研究了一晚之後,找遍了很多網站的資料,才發現不管是lshw還是dmidecode
他們的源代碼裡都是以run一個組言來取得這些資料,問題是同一台機器上面lshw取得
的CPUID與dmidecode所取得的居然不一樣,這下頭大了,到底誰才是對的??

但我自run debug讀取AX裡的資料是跟dmidecode所取得的前二碼是一樣的,所以我比
較相信dmidecode是對的,問題是AX裡應該是批號,那序號呢?比如下面
F8 06 00 00 FF EB EA 0A   ←由dmidecode所取得
-----          ------------
↑批號          ↑這應該是序號

這FF EB EA 0A 我還沒研究出來是如何取得的??
« 上次編輯: 2009-06-03 12:28 由 ebyaya »

ebyaya

  • 可愛的小學生
  • *
  • 文章數: 18
    • 檢視個人資料
經過小弟契而不捨的研究之後,終於真相大白了,就Intel的文件上看來所謂的CPUID其實分成
很多個部份。

第一當EAX=0時,所取得的是CPU的廠商代號,如Pentium III 代號為 GenuineIntel

第二當EAX=1時,所取得的是CPU的型號、類型、家族、功能等

第三當EAX=3時,所取得的是特徵碼,分佈於ECX及EDX裡

所以如果你是要取得CPU的唯一值,單取EAX=1是不夠的,依照Intel的說法
是必需把EAX=1的EAX值 + EAX=3的EDX + ECX 共96bit的code如此才能成為
CPU的唯一值。

請參照INTEL文件 http://www.intel.com/Assets/PDF/appnote/241618.pdf

kenduest

  • 酷!學園 學長們
  • 俺是博士!
  • *****
  • 文章數: 3675
    • 檢視個人資料
    • http://kenduest.sayya.org

多年前寫的 code

代碼: [選擇]
#include <stdio.h>
#include <sys/ioctl.h>
#include <linux/hdreg.h>
#include <sys/fcntl.h>

int main()
{
   struct hd_driveid id;

   int fd = open("/dev/hda", O_RDONLY|O_NONBLOCK);

   if (fd < 0) {
     perror("/dev/hda");
     return 1; }

    if(!ioctl(fd, HDIO_GET_IDENTITY, &id))
     {
       printf("Serial Number=%s\n",id.serial_no);
     }

    return 0;
}

測試結果:

代碼: [選擇]
# ./a.out
Serial Number=WD-WCAMR1807004
I am kenduest - 小州

my website: http://kenduest.sayya.org/

ebyaya

  • 可愛的小學生
  • *
  • 文章數: 18
    • 檢視個人資料

多年前寫的 code

代碼: [選擇]
#include <stdio.h>
#include <sys/ioctl.h>
#include <linux/hdreg.h>
#include <sys/fcntl.h>

int main()
{
   struct hd_driveid id;

   int fd = open("/dev/hda", O_RDONLY|O_NONBLOCK);

   if (fd < 0) {
     perror("/dev/hda");
     return 1; }

    if(!ioctl(fd, HDIO_GET_IDENTITY, &id))
     {
       printf("Serial Number=%s\n",id.serial_no);
     }

    return 0;
}

測試結果:

代碼: [選擇]
# ./a.out
Serial Number=WD-WCAMR1807004

大大多謝你的code,實際run了之後可用,
但有一個問題請教,此code run在ide有效,
run在sata無效,如何改?(已改過/dev/sda)

kenduest

  • 酷!學園 學長們
  • 俺是博士!
  • *****
  • 文章數: 3675
    • 檢視個人資料
    • http://kenduest.sayya.org

沒問題啊~~

代碼: [選擇]
SayyaBBS:kendlee@~/tmp> sudo hdparm -i /dev/sda

/dev/sda:

 Model=HDS728080PLA380                         , FwRev=PF2OA69A, SerialNo=      PFDH32S6SD8LZN
 Config={ HardSect NotMFM HdSw>15uSec Fixed DTR>10Mbs }
 RawCHS=16383/16/63, TrkSize=0, SectSize=0, ECCbytes=52
 BuffType=DualPortCache, BuffSize=7677kB, MaxMultSect=16, MultSect=?16?
 CurCHS=16383/16/63, CurSects=16514064, LBA=yes, LBAsects=160836480
 IORDY=on/off, tPIO={min:240,w/IORDY:120}, tDMA={min:120,rec:120}
 PIO modes:  pio0 pio1 pio2 pio3 pio4
 DMA modes:  mdma0 mdma1 mdma2
 UDMA modes: udma0 udma1 udma2 udma3 udma4 udma5 *udma6
 AdvancedPM=yes: disabled (255) WriteCache=enabled
 Drive conforms to: ATA/ATAPI-7 T13 1532D revision 1:  ATA/ATAPI-2,3,4,5,6,7

 * signifies the current active mode


代碼: [選擇]
SayyaBBS:kendlee@~/tmp> cat test.c
#include <stdio.h>
#include <sys/ioctl.h>
#include <linux/hdreg.h>
#include <sys/fcntl.h>

int main()
{
   struct hd_driveid id;

   int fd = open("/dev/sda", O_RDONLY|O_NONBLOCK);

   if (fd < 0) {
     perror("/dev/sda");
     return 1; }

    if(!ioctl(fd, HDIO_GET_IDENTITY, &id))
     {
       printf("Serial Number=%s\n",id.serial_no);
     }

    return 0;
}
SayyaBBS:kendlee@~/tmp> gcc test.c
SayyaBBS:kendlee@~/tmp> sudo ./a.out
Serial Number=      PFDH32S6SD8LZN
I am kenduest - 小州

my website: http://kenduest.sayya.org/

ebyaya

  • 可愛的小學生
  • *
  • 文章數: 18
    • 檢視個人資料
代碼: [選擇]
#in RH9
[root@localhost C]# hdparm -i /dev/sda

/dev/sda:
 operation not supported on SCSI disks

#in CentOS 5
[root@localhost C]# hdparm -i /dev/sda

/dev/sda:
 HDIO_GET_IDENTITY failed: Invalid argument


學長大大抱歉是我搞錯了,IDE和SATA是OK的,應該是SCSI硬碟不支援^^