在很多系统软件的开发中,需要使用一些系统的唯一性信息。所以,得到主机的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 shortconfig;/ lots of obsolete bit flags */
unsigned shortcyls;/* Obsolete, "physical" cyls */
unsigned shortreserved2;/* reserved (word 2) */
unsigned shortheads;/* Obsolete, "physical" heads */
unsigned shorttrack_bytes;/* unformatted bytes per track */
unsigned shortsector_bytes;/* unformatted bytes per sector */
unsigned shortsectors;/* Obsolete, "physical" sectors per track */
unsigned shortvendor0;/* vendor unique */
unsigned shortvendor1;/* vendor unique */
unsigned shortvendor2;/* Retired vendor unique */
unsigned charserial_no[20];/* 0 = not_specified */
unsigned shortbuf_type;/* Retired */
unsigned shortbuf_size;/* Retired, 512 byte increments