文章導航綠軟下載站軟件下載安卓資源蘋果資源專題

您當前所在位置:首頁操作系統LINUX → Linux下獲取CPUID、硬盤序列號與MAC地址

Linux下獲取CPUID、硬盤序列號與MAC地址

時間:2015/6/28來源:IT貓撲網作者:網管聯盟我要評論(0)

  在很多系統軟件的開發中,需要使用一些系統的唯一性信息。所以,得到主機的CPUID、硬盤序列號及網卡的MAC地址,就成個一件很重要的應用。

  本人經過一番google即自己的鉆研,基本上實現了這幾個功能。需要的準備知識有:

  GCC的嵌入匯編,具體的GCC嵌入匯編知識,請參考相關手冊

  ioctl系統調用,具體的調用方法,請查看手冊頁

  獲取CPUID

  按照網上提供的說明,CPUID并不是所有的Intel CPU都支持的。如果支持,匯編調用為:eax置0000_0003,調用cpuid。

  以下為實現代碼(在我的CPU上,并沒有得到):

  #define cpuid(in,a,b,c,d) asm("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (in));

  static int

  getcpuid (char *id, size_t max)

  {

  int i;

  unsigned long li, maxi, maxei, ebx, ecx, edx, unused;

  cpuid (0, maxi, unused, unused, unused);

  maxi &= 0xffff;

  if (maxi < 3)

  {

  return -1;

  }

  cpuid (3, eax, ebx, ecx, edx);

  snprintf (id, max, "%08lx %08lx %08lx %08lx", eax, ebx, ecx, edx);

  fprintf (stdout, "get cpu id: %s\n", id);

  return 0;

  }

  獲取硬盤序列號

  這個的實現,采用的是讀取/etc/mtab文件,找到/(即根目錄)掛載的設備文件,然后打開它,再用系統調用ioctl來實現的。

  ioctl第二個參數為HDIO_GET_IDENTITY, 獲得指定文件描述符的標志號

  ioctl的第三個參數為struct hd_driveid ,在linux/hdreg.h中,struct hd_driveid的聲明有

  struct hd_driveid {

  unsigned short config; / lots of obsolete bit flags */

  unsigned short cyls; /* Obsolete, "physical" cyls */

  unsigned short reserved2; /* reserved (word 2) */

  unsigned short heads; /* Obsolete, "physical" heads */

  unsigned short track_bytes; /* unformatted bytes per track */

  unsigned short sector_bytes; /* unformatted bytes per sector */

  unsigned short sectors; /* Obsolete, "physical" sectors per track */

  unsigned short vendor0; /* vendor unique */

  unsigned short vendor1; /* vendor unique */

  unsigned short vendor2; /* Retired vendor unique */

  unsigned char serial_no[20]; /* 0 = not_specified */

  unsigned short buf_type; /* Retired */

  unsigned short buf_size; /* Retired, 512 byte increments

  * 0 = not_specified

  */

  ……

  };

  ,這其中,serial_no為硬盤的序列號。如果此項為0,則為沒有提供。

  思路明確了,以下為實現代碼:

  static int

  getdiskid (char *id, size_t max)

  {

  int fd;

  struct hd_driveid hid;

  FILE *fp;

  char line[0x100], *disk, *root, *p;

  fp = fopen ("/etc/mtab", "r");

  if (fp == NULL)

  {

  fprintf (stderr, "No /etc/mtab file.\n");

  return -1;

  }

#p#副標題#e#

  fd = -1;

  while (fgets (line, sizeof line, fp) != NULL)

  {

  disk = strtok (line, " ");

  if (disk == NULL)

  {

  continue;

  }

  root = strtok (NULL, " ");

  if (root == NULL)

  {

  continue;

  }

  if (strcmp (root, "/") == 0)

  {

  for (p = disk + strlen (disk) - 1; isdigit (*p); p --)

  {

  *p = '\0';

  }

  fd = open (disk, O_RDONLY);

  break;

  }

  }

  fclose (fp);

  if (fd < 0)

  {

  fprintf (stderr, "open hard disk device failed.\n");

  return -1;

  }

  if (ioctl (fd, HDIO_GET_IDENTITY, &hid) < 0)

  {

  fprintf (stderr, "ioctl error.\n");

  return -1;

  }

  close (fd);

  snprintf (id, max, "%s", hid.serial_no);

  fprintf (stdout, "get hard disk serial number: %s\n", id);

  return 0;

  }

  獲取MAC地址

  通過創建一個socket,然后bind特定的IP地址,就可以通過ioctl得到這個套按地綁定的網絡接口名稱。然后再通過網絡接口名稱,得到MAC地址。

  如果ioctl的第二個參數為SIOCGIFNAME, 則獲得指定網絡接口的名稱;如果ioctl的第二個參數為SIOCGIFHWADDR,則獲得指定網絡接口的MAC地址

  ioctl的第三個參數為struct ifreq ,在linux/if.h頭文件里,struct ifreq聲明如下:

  struct ifreq

  {

  #define IFHWADDRLEN 6

  union

  {

  char ifrn_name[IFNAMSIZ]; / if name, e.g. "en0" */

  } ifr_ifrn;

  union {

  struct sockaddr ifru_addr;

  struct sockaddr ifru_dstaddr;

  struct sockaddr ifru_broadaddr;

  struct sockaddr ifru_netmask;

  struct sockaddr ifru_hwaddr;

  short ifru_flags;

  int ifru_ivalue;

  int ifru_mtu;

  struct ifmap ifru_map;

  char ifru_slave[IFNAMSIZ]; /* Just fits the size */

  char ifru_newname[IFNAMSIZ];

  void * ifru_data;

  struct if_settings ifru_settings;

  } ifr_ifru;

  }

#p#副標題#e#

  ,其中,ifrn_name為網絡接口的名稱,ifr_ifru.ifru_hwaddr為網絡接口的MAC地址。

  #ifndef MAX_IFINDEX

  # define MAX_IFINDEX 8

  #endif

  static int

  getmacaddr (const char *ip, char *id, size_t max)

  {

  int i, sockfd;

  struct sockaddr_in *loc;

  struct ifreq req[1];

  sockfd = socket (AF_INET, SOCK_DGRAM, 0);

  if (sockfd < 0)

  {

  fprintf (stderr, "Unable to create socket.\n");

  return -1;

  }

  for (i = 0; i <= MAX_IFINDEX; ++ i)

  {

  req->ifr_ifindex = i;

  if (ioctl (sockfd, SIOCGIFNAME, req) < 0)

  {

  fprintf (stderr, "ioctl error: %s\n", strerror (errno));

  continue;

  }

  if (ioctl (sockfd, SIOCGIFADDR, req) < 0)

  {

  fprintf (stderr, "ioctl interface index [%d] error: %s\n", i, strerror (errno));

  continue;

  }

  loc = (struct sockaddr_in *) (&(req->ifr_ifru.ifru_addr));

  if (loc->sin_addr.s_addr == inet_addr (ip))

  {

  fprintf (stderr, "%s bind at %s.\n", ip, req->ifr_name);

  break;

  }

  }

  if (i > MAX_IFINDEX)

  {

  fprintf (stderr, "input IP error.\n");

  close (sockfd);

  return -1;

  }

  if (ioctl (sockfd, SIOCGIFHWADDR, req) < 0)

  {

  fprintf (stderr, "ioctl error: %s\n", strerror (errno));

  close (sockfd);

  return -1;

  }

  close (sockfd);

  snprintf (id, max, "%02X%02X%02X%02X%02X%02X",

  req->ifr_hwaddr.sa_data[0] & 0xff,

  req->ifr_hwaddr.sa_data[1] & 0xff,

  req->ifr_hwaddr.sa_data[2] & 0xff,

  req->ifr_hwaddr.sa_data[3] & 0xff,

  req->ifr_hwaddr.sa_data[4] & 0xff,

  req->ifr_hwaddr.sa_data[5] & 0xff);

  fprintf (stdout, "MAC address of %s: [%s].\n", req->ifr_name, id);

  return 0;

  }

關鍵詞標簽:Linux,硬盤序列號,MAC

相關閱讀

文章評論
發表評論

熱門文章 使用Clonezilla遷移到虛擬Linux環境使用Clonezilla遷移到虛擬Linux環境Linux服務器:設計高性能網站架構-LLMPLinux服務器:設計高性能網站架構-LLMP安裝配置MRTG監控Linux網絡安裝配置MRTG監控Linux網絡Linux下的Root權限控制Linux下的Root權限控制

相關軟件

人氣排行 Linux下獲取CPUID、硬盤序列號與MAC地址linux tc實現ip流量限制dmidecode命令查看內存型號linux下解壓rar文件安裝紅帽子RedHat Linux9.0操作系統教程Ubuntu linux 關機、重啟、注銷 命令lcx.exe、nc.exe、sc.exe入侵中的使用方法查看linux服務器硬盤IO讀寫負載

野心不大怎样赚钱呢 炒股票在哪里开户 11选五中奖规则 双色球复式价格表 新疆十一选五开奖结果一定牛 内蒙古快三跨度和值走势图 安徽十一选5技巧 股票配资骗局亲身经历 陕西省11选五遗漏 快三彩票app免费下载 加拿大快乐8开奖号码