Linux下获取CPUID、硬盘序列号

在很多系统软件的开发中,需要使用一些系统的唯一性信息。所以,得到主机的CPUID、硬盘序列号及网卡的MAC地址,就成个一件很重要的应用。

需要的准备知识有:

1. GCC的嵌入汇编,具体的GCC嵌入汇编知识,请参考相关手册

2.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;		/</em> 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,则为没有提供。

思路明确了,以下为实现代码:

#include <string.h>
#include<stdio.h>
#include <sys/ioctl.h>
#include <linux/hdreg.h>
#include <fcntl.h>
#include <stdlib.h>
#include<ctype.h>

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;
}

 

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值