Linux下获取CPUID硬盘序列号与MAC地址.docx
- 文档编号:28801827
- 上传时间:2023-07-19
- 格式:DOCX
- 页数:8
- 大小:16.22KB
Linux下获取CPUID硬盘序列号与MAC地址.docx
《Linux下获取CPUID硬盘序列号与MAC地址.docx》由会员分享,可在线阅读,更多相关《Linux下获取CPUID硬盘序列号与MAC地址.docx(8页珍藏版)》请在冰豆网上搜索。
Linux下获取CPUID硬盘序列号与MAC地址
Linux下获取CPUID、硬盘序列号与MAC地址
在很多系统软件的开发中,需要使用一些系统的唯一性信息。
所以,得到主机的CPUID、硬盘序列号及网卡的MAC地址,就成个一件很重要的应用。
本人经过一番google即自己的钻研,基本上实现了这几个功能。
需要的准备知识有:
1.GCC的嵌入汇编,具体的GCC嵌入汇编知识,请参考相关手册
2.ioctl系统调用,具体的调用方法,请查看手册页
获取CPUID
按照网上提供的说明,CPUID并不是所有的IntelCPU都支持的。
如果支持,汇编调用为:
eax置0000_0003,调用cpuid。
以下为实现代码(在我的CPU上,并没有得到):
#definecpuid(in,a,b,c,d)asm("cpuid":
"=a"(a),"=b"(b),"=c"(c),"=d"(d):
"a"(in));staticint
getcpuid(char*id,size_tmax)
{
inti;
unsignedlongli,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,"getcpuid:
%s\n",id);
return0;
}
获取硬盘序列号
这个的实现,采用的是读取/etc/mtab文件,找到/(即根目录)挂载的设备文件,然后打开它,再用系统调用ioctl来实现的。
ioctl第二个参数为HDIO_GET_IDENTITY,获得指定文件描述符的标志号
ioctl的第三个参数为structhd_driveid*,在linux/hdreg.h中,structhd_driveid的声明有
structhd_driveid{
unsignedshortconfig;/*lotsofobsoletebitflags*/
unsignedshortcyls;/*Obsolete,"physical"cyls*/
unsignedshortreserved2;/*reserved(word2)*/
unsignedshortheads;/*Obsolete,"physical"heads*/
unsignedshorttrack_bytes;/*unformattedbytespertrack*/
unsignedshortsector_bytes;/*unformattedbytespersector*/
unsignedshortsectors;/*Obsolete,"physical"sectorspertrack*/
unsignedshortvendor0;/*vendorunique*/
unsignedshortvendor1;/*vendorunique*/
unsignedshortvendor2;/*Retiredvendorunique*/
unsignedcharserial_no[20];/*0=not_specified*/
unsignedshortbuf_type;/*Retired*/
unsignedshortbuf_size;/*Retired,512byteincrements
*0=not_specified
*/
……
};
这其中,serial_no为硬盘的序列号。
如果此项为0,则为没有提供。
思路明确了,以下为实现代码:
staticint
getdiskid(char*id,size_tmax)
{
intfd;
structhd_driveidhid;
FILE*fp;
charline[0x100],*disk,*root,*p;
fp=fopen("/etc/mtab","r");
if(fp==NULL)
{
fprintf(stderr,"No/etc/mtabfile.\n");
return-1;
}
fd=-1;
while(fgets(line,sizeofline,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,"openharddiskdevicefailed.\n");
return-1;
}
if(ioctl(fd,HDIO_GET_IDENTITY,&hid)<0)
{
fprintf(stderr,"ioctlerror.\n");
return-1;
}
close(fd);
snprintf(id,max,"%s",hid.serial_no);
fprintf(stdout,"getharddiskserialnumber:
%s\n",id);
return0;
}
获取MAC地址
通过创建一个socket,然后bind特定的IP地址,就可以通过ioctl得到这个套按地绑定的网络接口名称。
然后再通过网络接口名称,得到MAC地址。
如果ioctl的第二个参数为SIOCGIFNAME,则获得指定网络接口的名称;如果ioctl的第二个参数为SIOCGIFHWADDR,则获得指定网络接口的MAC地址
ioctl的第三个参数为structifreq*,在linux/if.h头文件里,structifreq声明如下:
structifreq
{
#defineIFHWADDRLEN6
union
{
charifrn_name[IFNAMSIZ];/*ifname,e.g."en0"*/
}ifr_ifrn;
union{
structsockaddrifru_addr;
structsockaddrifru_dstaddr;
structsockaddrifru_broadaddr;
structsockaddrifru_netmask;
structsockaddrifru_hwaddr;
shortifru_flags;
intifru_ivalue;
intifru_mtu;
structifmapifru_map;
charifru_slave[IFNAMSIZ];/*Justfitsthesize*/
charifru_newname[IFNAMSIZ];
void*ifru_data;
structif_settingsifru_settings;
}ifr_ifru;
}
其中,ifrn_name为网络接口的名称,ifr_ifru.ifru_hwaddr为网络接口的MAC地址。
#ifndefMAX_IFINDEX
#defineMAX_IFINDEX8
#endif
staticint
getmacaddr(constchar*ip,char*id,size_tmax)
{
inti,sockfd;
structsockaddr_in*loc;
structifreqreq[1];
sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd<0)
{
fprintf(stderr,"Unabletocreatesocket.\n");
return-1;
}
for(i=0;i<=max_IFINDEX;++i)
{
req->ifr_ifindex=i;
if(ioctl(sockfd,SIOCGIFNAME,req)<0)
{
fprintf(stderr,"ioctlerror:
%s\n",strerror(errno));
continue;
}
if(ioctl(sockfd,SIOCGIFADDR,req)<0)
{
fprintf(stderr,"ioctlinterfaceindex[%d]error:
%s\n",i,strerror(errno));continue;
}
loc=(structsockaddr_in*)(&(req->ifr_ifru.ifru_addr));
if(loc->sin_addr.s_addr==inet_addr(ip))
{
fprintf(stderr,"%sbindat%s.\n",ip,req->ifr_name);
break;
}
}
if(i==MAX_IFINDEX)
{
fprintf(stderr,"inputIPerror.\n");
close(sockfd);
return-1;
}
if(ioctl(sockfd,SIOCGIFHWADDR,req)<0)
{
fprintf(stderr,"ioctlerror:
%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,"MACaddressof%s:
[%s].\n",req->ifr_name,id);
return0;
}
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Linux 获取 CPUID 硬盘 序列号 MAC 地址