時間:2015-06-28 00:00:00 來源:IT貓撲網(wǎng) 作者:網(wǎng)管聯(lián)盟 我要評論(0)
在很多系統(tǒng)軟件的開發(fā)中,需要使用一些系統(tǒng)的唯一性信息。所以,得到主機(jī)的CPUID、硬盤序列號及網(wǎng)卡的MAC地址,就成個一件很重要的應(yīng)用。
本人經(jīng)過一番google即自己的鉆研,基本上實現(xiàn)了這幾個功能。需要的準(zhǔn)備知識有:
GCC的嵌入?yún)R編,具體的GCC嵌入?yún)R編知識,請參考相關(guān)手冊
ioctl系統(tǒng)調(diào)用,具體的調(diào)用方法,請查看手冊頁
獲取CPUID
按照網(wǎng)上提供的說明,CPUID并不是所有的Intel CPU都支持的。如果支持,匯編調(diào)用為:eax置0000_0003,調(diào)用cpuid。
以下為實現(xiàn)代碼(在我的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;
}
獲取硬盤序列號
這個的實現(xiàn),采用的是讀取/etc/mtab文件,找到/(即根目錄)掛載的設(shè)備文件,然后打開它,再用系統(tǒng)調(diào)用ioctl來實現(xiàn)的。
ioctl第二個參數(shù)為HDIO_GET_IDENTITY, 獲得指定文件描述符的標(biāo)志號
ioctl的第三個參數(shù)為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,則為沒有提供。
思路明確了,以下為實現(xiàn)代碼:
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;
}
#p#副標(biāo)題#e#
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地址
通過創(chuàng)建一個socket,然后bind特定的IP地址,就可以通過ioctl得到這個套按地綁定的網(wǎng)絡(luò)接口名稱。然后再通過網(wǎng)絡(luò)接口名稱,得到MAC地址。
如果ioctl的第二個參數(shù)為SIOCGIFNAME, 則獲得指定網(wǎng)絡(luò)接口的名稱;如果ioctl的第二個參數(shù)為SIOCGIFHWADDR,則獲得指定網(wǎng)絡(luò)接口的MAC地址
ioctl的第三個參數(shù)為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;
}
#p#副標(biāo)題#e#
,其中,ifrn_name為網(wǎng)絡(luò)接口的名稱,ifr_ifru.ifru_hwaddr為網(wǎng)絡(luò)接口的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;
}
關(guān)鍵詞標(biāo)簽:Linux,硬盤序列號,MAC
相關(guān)閱讀
熱門文章 安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程 Tomcat9.0如何安裝_Tomcat9.0環(huán)境變量配置方法 多種操作系統(tǒng)NTP客戶端配置 Linux操作系統(tǒng)修改IP
人氣排行 Linux下獲取CPUID、硬盤序列號與MAC地址 dmidecode命令查看內(nèi)存型號 linux tc實現(xiàn)ip流量限制 安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程 linux下解壓rar文件 lcx.exe、nc.exe、sc.exe入侵中的使用方法 Ubuntu linux 關(guān)機(jī)、重啟、注銷 命令 查看linux服務(wù)器硬盤IO讀寫負(fù)載