Linux下获取CPUID、硬盘序列号与MAC地址
2009-10-25 10:02
447 查看
在很多系统软件的开发中,需要使用一些系统的唯一性信息。所以,得到主机的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; } 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; } ,其中,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下获取CPUID、硬盘序列号与MAC地址
- Linux下获取CPUID、硬盘序列号与MAC地址
- 获取Mac、CPUID、硬盘序列号、本地IP地址、外网IP地址OCX控件
- 获取cpu序列号,硬盘ID,网卡MAC地址
- 用C#获取硬盘序列号,CPU序列号,网卡MAC地址的源码
- 用vbs脚本获取网卡MAC,CPUID,硬盘序列号
- 获取cpu序列号,硬盘ID,网卡MAC地址
- 获取cpu序列号,硬盘ID,网卡MAC地址
- shell获取mac地址及获取硬盘序列号的方法
- 关于获取系统信息,CPUID,硬盘ID,网卡MAC地址的VS2008实现
- 获取CPU序列号,硬盘ID,网卡MAC地址
- linux下获取CPUID,MAC地址,硬盘序列号,主板序列号
- C#获取硬盘序列号,CPU序列号,网卡MAC地址
- 获取cpu序列号,硬盘ID,网卡MAC地址
- 获取CPU序列号,硬盘序列号,网卡mac地址
- C#应用:获取cpu序列号,硬盘ID,网卡MAC地址
- 用C#获取硬盘序列号,CPU序列号,网卡MAC地址
- 获取cpu序列号,硬盘ID,网卡MAC地址
- 用C#获取硬盘序列号,CPU序列号,网卡MAC地址
- C#获取cpu序列号,硬盘ID,网卡MAC地址