在网上找了好长时间关于获取CPUID的代码,都不是完全版本,回去还得改,自己写好了,是借鉴dmidecode中的代码成完的,希望多多提意见,谢谢。
这样做的缺点是必须得有root权限才可以,其它用户的权限是不能进行访问/dev/mem这个文件。
types.h
-
#ifndef TYPES_H
-
#define TYPES_H
-
-
-
typedef unsigned char u8;
-
typedef unsigned short u16;
-
typedef signed short i16;
-
typedef unsigned int u32;
-
-
#ifdef BIGENDIAN
-
typedef struct {
-
u32 h;
-
u32 l;
-
} u64;
-
#else
-
typedef struct {
-
u32 l;
-
u32 h;
-
} u64;
-
#endif
-
-
#ifdef ALIGNMENT_WORKAROUND
-
static inline u64 U64(u32 low, u32 high)
-
{
-
u64 self;
-
-
self.l = low;
-
self.h = high;
-
-
return self;
-
}
-
#endif
-
-
#ifdef ALIGNMENT_WORKAROUND
-
# ifdef BIGENDIAN
-
# define WORD(x) (u16)((x)[1] + ((x)[0] << 8))
-
# define DWORD(x) (u32)((x)[3] + ((x)[2] << 8) + ((x)[1] << 16) + ((x)[0] << 24))
-
# define QWORD(x) (U64(DWORD(x + 4), DWORD(x)))
-
# else /* BIGENDIAN */
-
# define WORD(x) (u16)((x)[0] + ((x)[1] << 8))
-
# define DWORD(x) (u32)((x)[0] + ((x)[1] << 8) + ((x)[2] << 16) + ((x)[3] << 24))
-
# define QWORD(x) (U64(DWORD(x), DWORD(x + 4)))
-
# endif /* BIGENDIAN */
-
#else /* ALIGNMENT_WORKAROUND */
-
#define WORD(x) (u16)(*(const u16 *)(x))
-
#define DWORD(x) (u32)(*(const u32 *)(x))
-
#define QWORD(x) (*(const u64 *)(x))
-
#endif /* ALIGNMENT_WORKAROUND */
-
-
#endif
util.h
-
#include <sys/types.h>
-
#include <sys/ioctl.h>
-
#include <sys/socket.h>
-
#include <netinet/in.h>
-
#include <net/if.h>
-
#include <string.h>
-
-
#include "types.h"
-
-
struct dmi_header
-
{
-
u8 type;
-
u8 length;
-
u16 handle;
-
u8 *data;
-
};
-
-
int checksum(const u8 *buf, size_t len);
-
void *mem_chunk(size_t base, size_t len, const char *devmem);
-
u64 u64_range(u64 start, u64 end);
-
void to_dmi_header(struct dmi_header *h, u8 *data);
-
int get_cpuid(char *cpuid);
-
int get_mac(char* mac);
util.c
-
#include <sys/types.h>
-
#include <sys/stat.h>
-
-
#ifdef USE_MMAP
-
#include <sys/mman.h>
-
#ifndef MAP_FAILED
-
#define MAP_FAILED ((void *) -1)
-
#endif /* !MAP_FAILED */
-
#endif /* USE MMAP */
-
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <unistd.h>
-
#include <string.h>
-
#include <fcntl.h>
-
#include <errno.h>
-
-
#include "types.h"
-
#include "util.h"
-
-
static int myread(int fd, u8 *buf, size_t count, const char *prefix)
-
{
-
ssize_t r = 1;
-
size_t r2 = 0;
-
-
while (r2 != count && r != 0)
-
{
-
r = read(fd, buf + r2, count - r2);
-
if (r == -1)
-
{
-
if (errno != EINTR)
-
{
-
close(fd);
-
perror(prefix);
-
return -1;
-
}
-
}
-
else
-
r2 += r;
-
}
-
-
if (r2 != count)
-
{
-
close(fd);
-
fprintf(stderr, "%s: Unexpected end of file\n", prefix);
-
return -1;
-
}
-
-
return 0;
-
}
-
-
int checksum(const u8 *buf, size_t len)
-
{
-
u8 sum = 0;
-
size_t a;
-
-
for (a = 0; a < len; a++)
-
sum += buf[a];
-
return (sum == 0);
-
}
-
-
/*
-
* Copy a physical memory chunk into a memory buffer.
-
* This function allocates memory.
-
*/
-
void *mem_chunk(size_t base, size_t len, const char *devmem)
-
{
-
void *p;
-
int fd;
-
#ifdef USE_MMAP
-
size_t mmoffset;
-
void *mmp;
-
#endif
-
-
if ((fd = open(devmem, O_RDONLY)) == -1)
-
{
-
perror(devmem);
-
return NULL;
-
}
-
-
if ((p = malloc(len)) == NULL)
-
{
-
perror("malloc");
-
return NULL;
-
}
-
-
#ifdef USE_MMAP
-
#ifdef _SC_PAGESIZE
-
mmoffset = base % sysconf(_SC_PAGESIZE);
-
#else
-
mmoffset = base % getpagesize();
-
#endif /* _SC_PAGESIZE */
-
/*
-
* Please note that we don't use mmap() for performance reasons here,
-
* but to workaround problems many people encountered when trying
-
* to read from /dev/mem using regular read() calls.
-
*/
-
mmp = mmap(0, mmoffset + len, PROT_READ, MAP_SHARED, fd, base - mmoffset);
-
if (mmp == MAP_FAILED)
-
goto try_read;
-
-
memcpy(p, (u8 *)mmp + mmoffset, len);
-
-
if (munmap(mmp, mmoffset + len) == -1)
-
{
-
fprintf(stderr, "%s: ", devmem);
-
perror("munmap");
-
}
-
-
goto out;
-
-
#endif /* USE_MMAP */
-
-
try_read:
-
if (lseek(fd, base, SEEK_SET) == -1)
-
{
-
fprintf(stderr, "%s: ", devmem);
-
perror("lseek");
-
free(p);
-
return NULL;
-
}
-
-
if (myread(fd, p, len, devmem) == -1)
-
{
-
free(p);
-
return NULL;
-
}
-
-
out:
-
if (close(fd) == -1)
-
perror(devmem);
-
-
return p;
-
}
-
-
void to_dmi_header(struct dmi_header *h, u8 *data)
-
{
-
h->type = data[0];
-
h->length = data[1];
-
h->handle = WORD(data + 2);
-
h->data = data;
-
}
-
-
int get_cpuid(char *cpuid)
-
{
-
char devmem[10] = "/dev/mem";
-
u16 len;
-
u16 num;
-
size_t fp;
-
u8 *buf=NULL, *nbuf=NULL, *data, *p;
-
int i = 0;
-
if ((buf = mem_chunk(0xF0000, 0x10000, devmem)) == NULL)
-
{
-
free(buf);
-
return 0;
-
}
-
-
for (fp = 0; fp <= 0xFFF0; fp += 16)
-
{
-
if(memcmp(buf + fp, "_SM_", 4) == 0 && fp <= 0xFFE0)
-
{
-
len = WORD(buf + fp + 0x16);
-
num = WORD(buf + fp + 0x1C);
-
-
if (!checksum(buf + fp, (buf + fp)[0x05]) || memcmp(buf + fp + 0x10, "_DMI_", 5) != 0 || !checksum(buf + fp + 0x10, 0x0F))
-
{
-
free(buf);
-
return 0;
-
}
-
if ((nbuf = mem_chunk(DWORD(buf + fp + 0x18), len, devmem)) == NULL)
-
{
-
fprintf(stderr, "Table is unreachable, sorry.\n");
-
free(buf);
-
free(nbuf);
-
return 0;
-
}
-
data = nbuf;
-
while (i < num && data+4 <= nbuf + len)
-
{
-
u8 *next;
-
struct dmi_header h;
-
-
to_dmi_header(&h, data);
-
-
if (h.length < 4)
-
{
-
printf("Invalid entry length (%u). DMI table is "
-
"broken! Stop.\n\n", (unsigned int)h.length);
-
free(buf);
-
free(nbuf);
-
return 0;
-
}
-
-
next = data + h.length;
-
while (next - nbuf + 1 < len && (next[0] != 0 || next[1] != 0))
-
next++;
-
next += 2;
-
if (h.type ==4)
-
{
-
p = h.data + 0x08;
-
//printf("CPUID:%02X%02X%02X%02X%02X%02X%02X%02X\n", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
-
sprintf(cpuid, "%02X%02X%02X%02X%02X%02X%02X%02X", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
-
free(buf);
-
free(nbuf);
-
return 1;
-
}
-
data = next;
-
i++;
-
}
-
fp += 16;
-
}
-
}
-
free(buf);
-
free(nbuf);
-
return 0;
-
}
-
-
int get_mac(char* mac)
-
{
-
int sockfd;
-
struct ifreq tmp;
-
char mac_addr[30];
-
-
sockfd = socket(AF_INET, SOCK_STREAM, 0);
-
if( sockfd < 0)
-
{
-
perror("create socket fail\n");
-
return -1;
-
}
-
-
memset(&tmp,0,sizeof(struct ifreq));
-
strncpy(tmp.ifr_name,"eth0",sizeof(tmp.ifr_name)-1);
-
if( (ioctl(sockfd,SIOCGIFHWADDR,&tmp)) < 0 )
-
{
-
printf("mac ioctl error\n");
-
return -1;
-
}
-
-
sprintf(mac_addr, "%02x%02x%02x%02x%02x%02x",
-
(unsigned char)tmp.ifr_hwaddr.sa_data[0],
-
(unsigned char)tmp.ifr_hwaddr.sa_data[1],
-
(unsigned char)tmp.ifr_hwaddr.sa_data[2],
-
(unsigned char)tmp.ifr_hwaddr.sa_data[3],
-
(unsigned char)tmp.ifr_hwaddr.sa_data[4],
-
(unsigned char)tmp.ifr_hwaddr.sa_data[5]
-
);
-
close(sockfd);
-
memcpy(mac,mac_addr,strlen(mac_addr));
-
-
return 0;
-
}
getsysinfo.c
-
#include <stdio.h>
-
#include "util.h"
-
-
int main()
-
{
-
char cpuid[20], mac[20];
-
get_cpuid(cpuid);
-
printf("CPUID:%s\n", cpuid);
-
get_mac(mac);
-
printf("MAC:%s\n", mac);
-
return 0;
-
}
Makefile
-
# Copyright (C) Zhou Zhongbai 46784314@qq.com
-
-
CC = gcc
-
CFLAGS = -W -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-qual \
-
-Wcast-align -Wwrite-strings -Wmissing-prototypes -Winline -Wundef
-
#CFLAGS += -DBIGENDIAN
-
#CFLAGS += -DALIGNMENT_WORKAROUND
-
-
# When debugging, disable -O2 and enable -g.
-
CFLAGS += -O2
-
#CFLAGS += -g
-
-
# Pass linker flags here
-
LDFLAGS =
-
-
DESTDIR =
-
prefix = /usr/local
-
sbindir = $(prefix)/sbin
-
mandir = $(prefix)/share/man
-
man8dir = $(mandir)/man8
-
docdir = $(prefix)/share/doc/getcpuid
-
-
INSTALL := install
-
INSTALL_DATA := $(INSTALL) -m 644
-
INSTALL_DIR := $(INSTALL) -m 755 -d
-
INSTALL_PROGRAM := $(INSTALL) -m 755
-
RM := rm -f
-
-
# BSD make provides $MACHINE, but GNU make doesn't
-
MACHINE ?= $(shell uname -m 2>/dev/null)
-
-
PROGRAMS = getsysinfo
-
-
all : $(PROGRAMS)
-
-
#
-
# Programs
-
#
-
-
getsysinfo : getsysinfo.o util.o
-
$(CC) $(LDFLAGS) getsysinfo.o util.o -o $@
-
-
#
-
# Objects
-
#
-
-
getsysinfo.o : getsysinfo.c util.h
-
$(CC) $(CFLAGS) -c $< -o $@
-
util.o : util.c util.h
-
$(CC) $(CFLAGS) -c $< -o $@
-
-
#
-
# Commands
-
#
-
-
strip : $(PROGRAMS)
-
strip $(PROGRAMS)
-
-
install : install-bin install-man install-doc
-
-
uninstall : uninstall-bin uninstall-man uninstall-doc
-
-
install-bin : $(PROGRAMS)
-
$(INSTALL_DIR) $(DESTDIR)$(sbindir)
-
for program in $(PROGRAMS) ; do \
-
$(INSTALL_PROGRAM) $$program $(DESTDIR)$(sbindir) ; done
-
-
uninstall-bin :
-
for program in $(PROGRAMS) ; do \
-
$(RM) $(DESTDIR)$(sbindir)/$$program ; done
-
-
install-man :
-
$(INSTALL_DIR) $(DESTDIR)$(man8dir)
-
for program in $(PROGRAMS) ; do \
-
$(INSTALL_DATA) man/$$program.8 $(DESTDIR)$(man8dir) ; done
-
-
uninstall-man :
-
for program in $(PROGRAMS) ; do \
-
$(RM) $(DESTDIR)$(man8dir)/$$program.8 ; done
-
-
install-doc :
-
$(INSTALL_DIR) $(DESTDIR)$(docdir)
-
$(INSTALL_DATA) README $(DESTDIR)$(docdir)
-
$(INSTALL_DATA) CHANGELOG $(DESTDIR)$(docdir)
-
$(INSTALL_DATA) AUTHORS $(DESTDIR)$(docdir)
-
-
uninstall-doc :
-
$(RM) -r $(DESTDIR)$(docdir)
-
-
clean :
-
$(RM) *.o $(PROGRAMS)
阅读(15215) | 评论(0) | 转发(0) |