在很多系统软件的开发中,需要使用一些系统的唯一性信息。所以,得到主机的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;

}

【编辑推荐】

【责任编辑:faya TEL:(010)68476606】

linux获取机器cpuid地址函数,Linux下获取CPUID、硬盘序列号与MAC地址相关推荐

  1. JAVA获取CPUID、主板序列号、硬盘序列号、MAC地址

    最近在修改公司licence程序,需要获取到更多的硬件唯一标识,以便加密使用. 网上看了很多大神的博客,思路大概整理了一下,根据系统类型分为两种方式: 一.windows 通过创建vbs脚本,然后使用 ...

  2. 一键获取电脑的系统安装时间、硬盘序列号、MAC地址、补丁安装信息

    查询Windows电脑的操作系统安装时间.硬盘序列号.MAC地址.补丁安装数量.和最新补丁安装时间,都有相应的命令行查询命令.但是一个一个查询有点麻烦,用Python写了一个一键查询的方法. 可将如下 ...

  3. java MacBook air,macbook pro 与 macbook air 的区别!(前者是高配?java中如何读取主板序列号、硬盘序列号、MAC地址...

    所以我想问的重点是?(本人使用苹果①向用于上网?整体性能呢:air那么薄,那么轻,请问它的硬盘对比pro有什么利弊,对于air我①直用macbook pro,②年换①次,今年由于①③寸的并没有使用i系 ...

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

    ioctl系统调用,具体的调用方法,请查看手册页 获取CPUID 按照网上提供的说明,CPUID并不是所有的Intel CPU都支持的.如果支持,汇编调用为:eax置0000_0003,调用cpuid ...

  5. cpuid linux,Linux下获取CPUID、硬盘序列号与MAC地址(2)

    思路明确了,以下为实现代码: static int getdiskid (char *id, size_t max) { int fd; struct hd_driveid hid; FILE *fp ...

  6. win10查看设备序列号、硬盘序列号、mac地址

    1. 设备序列号 wmic bios get serialnumber 2. 查看硬盘序列号 wmic diskdrive get serialnumber 3. mac地址 控制面板\网络和 Int ...

  7. windows系统硬盘序列号、MAC地址查询方法

    硬盘序列号查询方法 进入命令行(cmd+R). 输入diskpart回车进入diskpart命令行. 输入list disk,列出所有磁盘和它们的磁盘号. 输入select disk ${磁盘号},选 ...

  8. linux查看设备和硬盘序列号 ip mac地址

    最近公司查设备,记录一下相关的命令,方便以后使用. 主要针对centos,ubuntu加上"sudo"应该就可以 : 几个命令都可以用 大家可以对比查看核对. 1 设备序列号 查看 ...

  9. 我们发现您的应用在用户同意隐私政策前申请获取用户个人信息(IMEI, 设备ID, 用户应用安装列表, MAC地址用户数据)

    一.需求 解决应用上架问题 过度获取用户信息 我们发现您的应用在用户同意隐私政策前申请获取用户个人信息(IMEI, 设备ID, 用户应用安装列表, MAC地址用户数据) 自"滴滴" ...

最新文章

  1. LabVIEW设计自定义滚动条
  2. Word中的字体大小
  3. 智能合约重构社会契约 (1)李嘉图合约
  4. 计算机专业伦理总结,《计算机伦理学》节译实践报告
  5. 内涵!!!程序猿才懂的动图...
  6. ASP.NET中使用C#文件下载四方法
  7. 俗语:“生不睡柳,死不睡杨”,有什么道理?
  8. [转]恢复 git reset -hard 的误操作
  9. uwsgi怎么启动停止
  10. DigitalFilmTools Rays 2.1.2汉化版|丁达尔光束耶稣光滤镜插件
  11. java QQ向另一个QQ发信息(可以是好友,也可以是非好友)
  12. 微信开发者工具封装request请求
  13. H5 App实现热更新,不需要重新安装app
  14. Android自定义控件--仿安全卫士中的一键加速【圆形进度条】
  15. Unity透明度不叠加
  16. Unity3D-设置地形
  17. 年底不要慌,这个EXCEL模板帮你打赢Q4收官战
  18. 线阵ccd模块LCAMV8-S11639-01/S11638高灵敏线阵图像传感器模组、驱动板
  19. Caused by: java.lang.IllegalArgumentException报错
  20. 数据库(My SQL 、SQL Server)的数据类型

热门文章

  1. 程控交换机分机同时拨打外线的方法
  2. 劲舞团显示服务器断接,为什么劲舞团网络连接中断?有哪些原因?
  3. Qt编写物联网管理平台42-数据查询导出打印
  4. 工学中计算机系专业的大学有哪些,大学理科专业有哪些
  5. 基于YoloV3卫星图像的储油罐容积占用率研究
  6. bigquant量化平台数据精准吗?
  7. 如何使用IntelliJ IDEA的Favorites来管理项目中的常用代码
  8. Python基础 笔记(一) Python的介绍
  9. redis未授权访问getshell的方式
  10. 计算机加硬盘后速度变慢,ssd硬盘win10系统加上机械硬盘后启动很慢怎么修复