Jianqiu 的个人资料猪圈照片日志列表 工具 帮助

日志


1月10日

如何读取CPU的频率?

如何读取CPU的频率?
 
公式:CPU频率=倍频*外频。
 
这三个数据,我们至少要得到两个,就可以计算出第三个数据了。
 
倍频总是可以非常容易的从寄存器里面读到的,比如AMD的CPU,直接从MSR寄存器里面读取即可。
 
自从Intel Pentium开始加了RDTSC指令之后,读取CPU的频率就变得非常简单了。调用RDTSC指令之后,就可以直接得到CPU频率。再除以倍频,就可以获取外频。
 
但是,在自动降频之类的节能技术出现之后,CPU的频率又变得飘忽不定了。进入节能状态之后,CPU的倍频会被降低。而RDTSC的读数,却总是对应POST时设置的固定倍频乘以即时的外频。这就需要将RDTSC的读数除以POST时设置的倍频,计算出外频,再乘以当前的倍频,计算出CPU当前频率。
 
公式:CPU频率=RDTSC频率/POST倍频*倍频
 
POST时设置的倍频,BIOS并没有记录下来供我们读取。所以这条路走不通了。
 
那么我只好将目光转向最麻烦的外频了,因为外频是由CPU外部的时钟发生器输入的,不同的主板上会有不同的时钟发生器,不同牌子不同型号的,常见的至少有七八种,读取方法都不一样。更要命的是,程序根本无法知道主板上装的是什么型号的时钟发生器。除非要用户拆开机箱,在密密麻麻的主板上,拿着放大镜找到那颗小小芯片,再到程序中选择正确的型号。这个几乎是不可能的了。。。
 
在研究了CPUZ的读取CPU频率的汇编代码之后,发现它是计算出外频,再乘以倍频来获得CPU频率的。外频的数值是从Local APIC的寄存器中获取,即0xFEE000000开始的几个寄存器,这个基地址基本是固定的,也可以从ACPI的MADT表中读到。在Linux中,这个Timer是用来触发进程调度器的,估计windows下应该也是这么搞的。因此,当我们利用这个Timer来计算外频的时候,还可以顺便保证了计算线程不会被切换走。此外,对于多核CPU,每个核心有自己的Local APIC,读取前要切换到对应的核心上。
 
仅仅可以读取外频的数值还不行,还需要计时。CPUZ里面调用了ACPI中定义的一个PM Timer来做计时器,该计时器的晶振频率是固定的:3.579545MHz,因此可以用来计算时间。该PM Timer是从IO端口读取的,端口号不同机器不一定相同,可以在ACPI的FADT表里读到。
 
这种做法在网上还没见到过,因此记录一下,以飨后人

评论

请稍候...
很抱歉,您输入的评论太长。请缩短您的评论。
您没有输入任何内容,请重试。
很抱歉,我们当前无法添加您的评论。请稍后重试。
若要添加评论,需要您的家长授予您相应权限。请求权限
您的家长禁用了评论功能。
很抱歉,我们当前无法删除您的评论。请稍后重试。
您已超过了一天之内允许提供的评论数上限。请在 24 小时后重试。
因为我们的系统表明您可能在向其他用户提供垃圾评论,您的帐户已禁用了评论功能。如果您认为我们错误地禁用了您的帐户,请联系 Windows Live 支持部门
完成下面的安全检查,您提供评论的过程才能完成。
您在安全检查中键入的字符必须与图片或音频中的字符一致。

若要添加评论,请使用您的 Windows Live ID 登录(如果您使用过 Hotmail、Messenger 或 Xbox LIVE,您就拥有 Windows Live ID)。登录


还没有 Windows Live ID 吗?请注册

引用通告

此日志的引用通告 URL 是:
http://zhujianqiu.spaces.live.com/blog/cns!D2AD9BF23E9ED5EA!415.trak
引用此项的网络日志