利用cpuid获取cpu信息,包括序列号,类型名等,还有另一种方法就是dmidecode的源码来实现,需要root权限,读取dev/mem
这里只列出cpuid的方法:
嵌入式汇编的说明:
例子:
asm volatile ("cpuid"
: "=a"(eax)
: "a"(1)
);
其中嵌入式汇编代码中,“a”(1)和"0"(1)是相同的,均表示eax = 1,即数字代表下标,英文字母为定义的变量,如“=a”(eax),其下标为0;
完整代码如下:
#include <stdio.h>
//其中嵌入式汇编代码中,“a”(1)和"0"(1)是相同的,均表示eax = 1,即数字代表下标,英文字母为定义的变量,如“=a”(eax),其下标为0
//
int main()
{
unsigned int eflags1, eflags2 = 0;
unsigned int eax = 0;
unsigned int ebx,ecx,edx;
/**
* eax == 1,则在eax中返回Family/Model/Stepping等信息
* [0:3] stepping
* [4:7] model
* [8:11] family
* [12:13] processor type
* [16:19] extended model ID
* [20:27] extended family ID
*/
asm volatile ("cpuid"
: "=a"(eax)
: "a"(1)
);
// printf("eax is %p/n", eax);
printf("Extended Family\t: %d\n", (0xff00000 & eax) >> 20);
printf("Extended Model\t: %d\n", (0xf0000 & eax) >> 16);
printf("Processor type\t: %d\n", (0x3000 & eax) >> 12);
printf("Family\t\t: %d\n", (0xf00 & eax) >> 8);
printf("Model\t\t: %d\n", (0xf0 & eax) >> 4);
printf("Stepping:\t: %d\n", (0xf & eax));
printf("/n");
/**
* eax == 0x800000000
* 如果CPU支持Brand String,则在EAX中返 >= 0x80000004的值。
*/
asm volatile ("cpuid"
: "=a"(eax)
: "a"(0x80000000)
);
printf("Is CPU support Brand String? %s\n", eax >= 0x80000004? "yes":"no");
printf("/n");
/**
* 如果支持Brand String,则EAX从0x80000002到0x80000004,每次增1,CPUID指令返回:
* EAX : Processor Brand String
* EBX : Processor Brand String Continued
* ECX : Processor Brand String Continued
* EDX : Processor Brand String Continued
*/
if(eax >= 0x80000004) {
unsigned int brands[4]; //每次的eax、ebx、ecx、edx
unsigned int i;
printf("Brand String/t: ");
for (i = 0x80000002; i <= 0x80000004; i++) {
asm volatile ("cpuid"
: "=a"(brands[0]), "=b"(brands[1]), "=c"(brands[2]), "=d"(brands[3])
: "0" (i)
);
printf("%s", (char *)brands);
}
//FIXME: 打出来的字符串是:In^Htel(R) Pentium(R^H) D CPU 2.80GHz
//其中^H是个不可见字符,会把它前一个吃掉
printf("\n");
}
/**
* eax == 0
* eax : cpuid指令允许的最大eax输入值
* ebx : "Genu"
* ecx : "ntel"
* edx : "inel"
*/
asm volatile ("cpuid"
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
: "0"(0) );
printf("Maximum CPUID Input EAX : %d\n", eax);
char string[128];
snprintf(string, 5, "%s", (char *)&ebx);
snprintf(string + 4, 5, "%s", (char *)&edx);
snprintf(string + 8, 5, "%s", (char *)&ecx);
printf("Vendor\t\t: %s\n", string);
printf("\n");
/**
* eax == 1,
* edx的第18比特为1,则CPU支持serial number
* 为0,则不支持,或者被disabled
* 序列号有96位,其中最高32位即是eax的输出值。应当把它保存下来,然后
* 再设置eax==3, 取剩下的64位
*/
asm volatile ("cpuid"
: "=a"(eax), "=d"(edx)
: "a"(1)
);
printf("%08x:%08x\n",ecx,edx);
printf("%08x:%08x\n",eax,edx);
if ( edx & (1 << 18) ) {
/* serial number supported */
/* edx输出中间32位的序列号,ecx输出最低32位的序列号 */
asm volatile ("cpuid"
: "=c"(ecx), "=d"(edx)
: "a"(3)
);
printf("Serial Number\t : %x-%x-%x-%x-%x-%x\n",
eax >> 16, eax << 16, edx >> 16, edx << 16, ecx >> 16, ecx << 16);
} else
printf("Serial Number not supported.\n");
printf("/n");
/**
* eax == 80000006h,返回L2 Cache的信息
*
* ecx[31:16] : L2 Cache size, in Kbytes
* ecx[15:12] : L2 Cache Associativity
* 00h disabled
* 01h direct mapped
* 02h 2-Way
* 04h 4-Way
* 06h 8-Way
* 08h 16-Way
* 0Fh Fully associative
* ecx[7:0] : L2 Cache Line size in bytes
*/
asm volatile ("cpuid"
: "=c"(ecx)
: "a"(0x80000006)
);
printf("L2 Cache Size\t : %dKbytes\n", ( ecx >> 16 ) );
printf("L2 Cache Line Size\t : %dbytes\n", (ecx & 0xff));
printf("L2 Cache Associativity\t : ");
switch ( (ecx & 0xf000) >> 12 )
{
case 0x00:
printf("%s\n", "disabled");
break;
case 0x01:
printf("%s\n", "direct mapped");
break;
case 0x02:
printf("%s\n", "2-Way");
break;
case 0x04:
printf("%s\n", "4-Way");
break;
case 0x06:
printf("%s\n", "8-Way");
break;
case 0x08:
printf("%s\n", "16-Way");
break;
case 0x0f:
printf("Fully associative");
break;
default:
printf("No such entry..\n");
}
printf("\n");
/**
* Input : eax == 4 && ecx == 0
*
* (eax[31:26] + 1) 是该物理处理器package上实现的core CPUs数目
*/
asm volatile ("cpuid"
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
: "0"(4), "2"(0)
);
printf("Number of Cores on this physical package\t : %d\n", (eax >> 27) + 1 );
printf("\n");
/**
* Input : eax == 1,则edx返回feature flag
*
*/
return 0;
}