IT猫扑网:您身边最放心的安全下载站! 最新更新| 软件分类| 专题汇总| 手机版

您当前所在位置:IT猫扑网 > 操作系统 > LINUX > Linux下获取CPUID、硬盘序列号与MAC地址

Linux下获取CPUID、硬盘序列号与MAC地址

时间:2015-06-28 00:00 来源:IT猫扑网|http://www.itmop.com/ 作者:网管联盟 我要评论(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: %sn&, 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 = '';

  }

  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: %sn&, 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: %sn&, strerror (errno));

  continue;

  }

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

  {

  fprintf (stderr, &ioctl interface index [%d] error: %sn&, 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: %sn&, 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

相关阅读 安装红帽子RedHat Linux9.0操作系统教程 Tomcat9.0如何安装_Tomcat9.0环境变量配置方法 多种操作系统NTP客户端配置 Linux操作系统修改IP Linux实现SCSI硬盘热插拔及在线识别 Linux下用CDMA modem拨号上网

文章评论
发表评论

热门文章 安装红帽子RedHat Linux9.0操作系统教程 安装红帽子RedHat Linux9.0操作系统教程 Linux服务器:设计高性能网站架构-LLMP Linux服务器:设计高性能网站架构-LLMP 使用Clonezilla迁移到虚拟Linux环境 使用Clonezilla迁移到虚拟Linux环境 Linux上的MRTG流量监控中心 Linux上的MRTG流量监控中心 Linux 双网卡绑定一个IP原理及实现 Linux 双网卡绑定一个IP原理及实现 linux和windows等系统远程控制ubuntu桌面 linux和windows等系统远程控制ubuntu桌面

相关下载

人气排行 Linux下获取CPUID、硬盘序列号与MAC地址 dmidecode命令查看内存型号 linux tc实现ip流量限制 安装红帽子RedHat Linux9.0操作系统教程 linux下解压rar文件 lcx.exe、nc.exe、sc.exe入侵中的使用方法 Ubuntu linux 关机、重启、注销 命令 查看linux服务器硬盘IO读写负载 linux命令行浏览器的使用方法 Linux NFS服务固定端口及防火墙配置 U盘安装Ubuntu 10.04 Linux清除用户登录记录和命令历史方法