首页 新闻 工控搜 论坛 厂商论坛 产品 方案 厂商 人才 文摘 下载 展览
中华工控网首页
  P L C | 变频器与传动 | 传感器 | 现场检测仪表 | 工控软件 | 人机界面 | 运动控制
  D C S | 工业以太网 | 现场总线 | 显示调节仪表 | 数据采集 | 数传测控 | 工业安全
  电 源 | 嵌入式系统 | PC based | 机柜箱体壳体 | 低压电器 | 机器视觉
Linux内核学习之BogoMIPS值的计算
深圳市盈鹏飞科技有限公司
收藏本文     查看收藏
   对于每一个linux编程爱好者来说,他们都有一个共同的心愿,就是了解linux的内核。但是linux内核的庞大与复杂让人望而生畏。往往是鼓足勇气一头扎进去,学得昏天黑地的,却没有学到什么。这里我想说,初学者不妨先学习学习内核中一些简单的函数,从中既可以得到乐趣,又能了解到内核的一些编程风格。然后,再将linux划分成几个部分,如进程调度、内存管理等,对每个部分从原理上去把握了解。接着,在详细分析各个部分的具体实现。最后,各部分串在一起,把过去单独分析时,不懂的地方加以重新了解。这样循环监禁,可以让我们更快更系统的学习linux的内核。
   这是我对内核学习的一些理解,欢迎各位提宝贵意见。我今天向大家介绍的是linux内核中一个有趣的函数calibrate_delay()。
   calibrate_delay()函数可以计算出cpu在一秒钟内执行了多少次一个极短的循环,计算出来的值经过处理后得到BogoMIPS值,Bogo是Bogus(伪)的意思,MIPS是millions of instructions per second(百万条指令每秒)的缩写。这样我们就知道了其实这个函数是linux内核中一个cpu性能测试函数。由于内核对这个数值的要求不高,所以内核使用了一个十分简单而有效的算法用于得到这个值。这个值虽然不准确,但也足以令我们心动。如果你想了解自己机器的BogoMIPS,你可以察看/proc/cpuinfo文件中的最后一行。在你知道了自己cpu的BogoMIPS之后,如果你觉得不过瘾,那么让我们一起来看看calibrate_delay函数是怎么完成工作的。
   下面是calibrate_delay的源代码,我在每行之前都加上了行号,以便讲解。
   1 #define LPS_PREC 8
   2 void __init calibrate_delay(void)
   3 {
   4  unsigned long ticks,loopbit;
   5  int lps_precision=LPS_PREC
   6 
   7  loops_per_sec=(1<<12);
   8 
   9  printk(“Calibrating delay loop…”);
   10  while(loops_per_sec<<=1) {
   11   /* wait for “start of” clock tick */
   12   ticks=jiffies;
   13   while(ticks==jiffies)
   14    /* nothing */;
   15   /* Go… */
   16   ticks=jiffies;
   17   __delay(loops_per_sec);
   18   ticks=jiffies-ticks;
   19   if(ticks)
   20    break;
   21  }
   22 
   23 /* Do a binary approximation to get loops_per_second set
   24 * to equal one clock (up to lps_precision bits) */
   25  loops_per_sec >>=1;
   26  loopbit=loop_per_sec;
   27  while(lps_precision-- && (loopbit >>=1) ) {
   28   loops_per_sec |= loopbit;
   29   ticks=jiffies;
   30   while(ticks==jiffies);
   31   ticks=jiffies;
   32   __delay(loops_per_sec);
   33   if(jiffies!=ticks) /* longer than 1 tick */
   34    loops_per_sec &=~loopbit;
   35  }
   36 /* finally,adjust loops per second in terms of seconds
   37 * instead of clocks */
   38  loops_per_sec *= HZ;
   39 /* Round the value and print it */
   40  printk(“%lu.%02lu BogoMIPSn”,
   41   (loops_per_sec+2500)/500000,
   42   ((loops_per_sec+2500)/5000) % 100);
   43 }
   对calibrate_delay()函数分析如下:
   1 定义计算BogoMIPS的精度,这个值越大,则计算出的BogoMIPS越精确。
   7 loops_per_sec为每秒钟执行一个极短的循环的次数。
   9 printk()是内核消息日志打印函数,用法同printf()函数。
   10 第10至21行,是第一次计算loops_per_sec的值,这次计算只是一个粗略的计算,为下面的计算打好基础。
   11 第11 至16行,是用于等待一个新的定时器滴答(它大概是百万分之一秒)的开始。可以想象我们要计算loops_per_sec的值,可以在一个滴答的开始时,立即重复执行一个极短的循环,当一个滴答结束时,这个循环执行了多少次就是我们要求的初步的值,再用它乘以一秒钟内的滴答数就是loops_per_sec的值。
   12 系统用jiffies全局变量记录了从系统开始工作到现在为止,所经过的滴答数。它会被内核自动更新。这行语句用于记录当前滴答数到tick变量中。
   13 注意这是一个没有循环体得空循环,第14行仅有一个“;”号。这条循环语句是通过判断tick的值与jiffies的值是否不同,来判断jiffies是否变化,即是否一个新的滴答开始了
   16 记录下新的滴答数以备后用。
   17 根据loops_per_sec值进行延时(及执行loop_per_sec次极短循环)。
   18 以下三行用于判断执行的延时是否超过一个滴答。一般loops_per_sec的初始值并不大,所以循环会逐步加大loops_per_sec的值,直到延时超过一个滴答。我们可以看出,前一次loops_per_sec的值还因太小不合适时,经过一次增大,它提高了两倍,满足了循环条件,跳出循环,而这个值实在是误差太大,所以我们还要经过第二次计算。这里还要注意的是通过上面的分析,我们可以知道更加精确的loops_per_sec的值应该在现在的值与它的一半之间。
   23 这里开始就是第二次计算了。它用折半查找法在我们上面所说的范围内计算出了更精确的loops_per_sec的值。
   25 义查找范围的最小值,我把它称为起点。
   26 定义查找范围,这样我们就可以看到loop_per_sec的值在“起点”与“起点加范围(终点)”之间。
   27 进入循环,将查找范围减半。
   28 重新定义起点,起点在“原起点加27行减半范围”处,即新起点在原先起点与终点的中间。这时我们可以看出loops_per_sec在“新起点”与“新起点加减半范围(新终点)”之间。
   29 第29至32行与第12至17行一致,都是等待新的滴答,执行延时。
   33 如果延时过短,说明loops_per_sec的值小了,将会跳过这部分,再次进入循环。它将是通过不断的折半方式来增大。如果延时过长,说明loops_per_sec的值大了,将起点重新返回原起点,当再次进入循环,由于范围减半,故可以达到减小的效果。
   38 计算出每秒执行极短循环的次数。从这里我们可以看出它好像是个死循环,所以加入了lps_precision变量,来控制循环,即LPS_PREC越大,循环次数越多,越精确。可能这些不太好懂,总的说来,它首先将loop_per_sec的值定为原估算值的1/2,作为起点值(我这样称呼它),以估算值为终点值.然后找出起点值到终点值的中间值.用上面相同的方法执行一段时间的延时循环.如果延时超过了一个tick,说明loop_per_sec值偏大,则仍以原起点值为起点值,以原中间值为终点值,以起点值和终点值的中间为中间值继续进行查找,如果没有超过一个tick,说明loop_per_sec偏小,则以原中间值为起点值,以原终点值为终点值继续查找。
   40 出BogoMIPS,并打印。
   至此,我们就分析完了calibrate_delay()函数。你从中学到了什么没有?如果你还有什么不明白的地方,可以给我发Email,如果你认为有什么更好的方法,欢迎来信我们一同探讨,我的Email是:feixiangniao@sina.com

 

状 态: 离线

公司简介
产品目录

公司名称: 深圳市盈鹏飞科技有限公司
联 系 人: 李希岗
电  话: 0086-13602511395
传  真: 0755-82523175,82523176-819
地  址: 深圳市福田区福明路40号,雷圳大厦12A06
邮  编: 518033
主  页:
 
该厂商相关技术文摘:
WINCE下如何添加CPL应用程序
Wince sqlite3移植
EAC-C925开机画面实现手册
英贝德推出单板机产品软件升级解决方案(WinCE篇)
EP9315电路设计要点
Linux下创建和使用RamDisk的技巧
英贝德科技移植PPP大揭秘:PPP拨号在ARM2410平台上的移植
AT91SAM9263在人机界面方面的应用
详解WinCE下USB Host驱动开发(2)
详解WinCE下USB Host驱动开发(1)
WinCE驱动中设备中断的处理
更多文摘...
立即发送询问信息在线联系该技术文摘厂商:
用户名: 密码: 免费注册为中华工控网会员
请留下您的有效联系方式,以方便我们及时与您联络

关于我们 | 联系我们 | 广告服务 | 本站动态 | 友情链接 | 法律声明 | 不良信息举报
工控网客服热线:0755-86369299
版权所有 中华工控网 Copyright©2022 Gkong.com, All Rights Reserved