在分析Arm+linux启动信息的时候。发现有一个信息竟然耗费了2s的时间,这简直是不能忍受的。这个耗时大鳄是什么东西哪,请看分析信息:

[    0.000000] console [ttyMT0] enabled

[    2.057770] Calibrating delay loop... 1694.10 BogoMIPS (lpj=4235264)

[    2.102188] pid_max: default: 32768 minimum: 301

针对上述信息,有很多疑惑,一点一点来分析。

1.何为BogoMIPS

BogoMIPS (Bogo--Bogus--伪的,MIPS--millions of instruction per second) 按照字面的解释是“不太真实的MIPS”。之所以不太真实,那是因为其计算方法并不十分精确。BogoMIPS的值在系统系统时,在一闪而过的启动信息里可以看到;也可以dmesg看到;还可以通过查看/proc/cpuifo看到。BogoMIPS 的值是 linux 内核通过在一个时钟节拍里不断的执行循环指令而估算出来,它实际上反应了 CPU 的速度。

2.怎么计算BogoMIPS

“Calibrating delay loop... 1694.10 BogoMIPS”来自文件init/ calibrate.c中的函数calibrate_delay(),该函数主要作用根据不同的配置计算BogoMIPS的值。

void __cpuinit calibrate_delay(void)
{
unsigned long lpj;
static bool printed; if (preset_lpj) {
lpj = preset_lpj;
if (!printed)
pr_info("Calibrating delay loop (skipped) "
"preset value.. ");
} else if ((!printed) && lpj_fine) {
lpj = lpj_fine;
pr_info("Calibrating delay loop (skipped), "
"value calculated using timer frequency.. ");
} else if ((lpj = calibrate_delay_direct()) != 0) {
if (!printed)
pr_info("Calibrating delay using timer "
"specific routine.. ");
} else {
if (!printed)
<strong> pr_info("Calibrating delay loop... ");
</strong>lpj = calibrate_delay_converge();
}
if (!printed)
<strong> pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
lpj/(500000/HZ),
(lpj/(5000/HZ)) % 100, lpj);</strong> loops_per_jiffy = lpj;
printed = true;
}

这其中有两个全局变量需要分析,他们是preset_lpjlpj_fine。定义在文件init/calibrate.c中:

unsigned long lpj_fine;

unsigned long preset_lpj;

在linux gcc言,unsigned long变量默认赋值为0。

另外,printed表示信息仅仅打印一次。

 

1. 若preset_lpj不为0

preset_lpj初值为0。

preset_lpj的赋值是有函数lpj_setup设置而来,该参数是有kernel bootloader设置而来。

unsigned long preset_lpj;

static int __init lpj_setup(char *str)

{

preset_lpj = simple_strtoul(str,NULL,0);

return 1;

}

__setup("lpj=", lpj_setup);

若preset_lpj不为0,表示lpj的值已经由用户预置,无需内核再行计算,直接赋值给lpj既可。

2. 否则,若printed为0 且 lpj_fine不为0

printed默认为0,只需观察lpj_fine的值既可以。

lpj_fine很简单,如果其不为0,表示该变量是有timer来计算的,无需再行计算,赋值给lpj既可。

3. 否则,若 calibrate_delay_direct()不等于0

查找配置文件,可以发现很多时候ARCH_HAS_READ_CURRENT_TIMER配置项都是没有设置的,因为calibrate_delay_direct()会直接返回0。

4. 其他

需要分析calibrate_delay_converge(),该函数是主力函数。

/*
* This is the number of bits of precision for the loops_per_jiffy. Each
* time we refine our estimate after the first takes 1.5/HZ seconds, so try
* to start with a good estimate.
* For the boot cpu we can skip the delay calibration and assign it a value
* calculated based on the timer frequency.
* For the rest of the CPUs we cannot assume that the timer frequency is same as
* the cpu frequency, hence do the calibration for those.
*/
#define LPS_PREC 8 static unsigned long __cpuinit calibrate_delay_converge(void)
{
/* First stage - slowly accelerate to find initial bounds */
unsigned long lpj, lpj_base, ticks, loopadd, loopadd_base, chop_limit;
int trials = 0, band = 0, trial_in_band = 0; lpj = (1<<12);/* 初始化为4096 */
/* wait for "start of" clock tick */
/* ticks保存当前jiffies的值。在while()中,只要ticks == jiffies,那么就一直执行空语句,也就是,只要时钟节拍还没更新则一直等待;注:系统用jiffies全局变量记录了从系统开始工作到现在为止,所经过的时钟节拍数 */
ticks = jiffies;
while (ticks == jiffies)
; /* nothing */
/* Go .. */
/* 估算一个时钟节拍内可执行的循环次数 */
ticks = jiffies;
do {
if (++trial_in_band == (1<<band)) {
++band;
trial_in_band = 0;
}
__delay(lpj * band);
trials += band;
} while (ticks == jiffies);
/*
* We overshot, so retreat to a clear underestimate. Then estimate
* the largest likely undershoot. This defines our chop bounds.
*/
trials -= band;
loopadd_base = lpj * band;
lpj_base = lpj * trials; recalibrate:
lpj = lpj_base;/* lpj取估算值为初值,精确度大约为tick/2(若band=2) */
loopadd = loopadd_base; /*
* Do a binary approximation to get lpj set to
* equal one clock (up to LPS_PREC bits)
*/
/* 采用二分法的方式,无限靠近真值 */
chop_limit = lpj >> LPS_PREC; /* 用于控制循环计算的次数 */
while (loopadd > chop_limit) {
lpj += loopadd;
ticks = jiffies;
while (ticks == jiffies)
; /* nothing */
ticks = jiffies;
__delay(lpj);
if (jiffies != ticks) /* longer than 1 tick */
lpj -= loopadd;
loopadd >>= 1;
}
/*
* If we incremented every single time possible, presume we've
* massively underestimated initially, and retry with a higher
* start, and larger range. (Only seen on x86_64, due to SMIs)
*/
/* 若每一次都是递增的(可能低估了lpj),则需要使用较大的初值和步幅 */
if (lpj + loopadd * 2 == lpj_base + loopadd_base * 2) {
lpj_base = lpj;
loopadd_base <<= 2;
goto recalibrate;
} return lpj;
}

3.BogoMIPS的用途

对于特定的CPU,BogoMips可用来查看它是否是个合适的值.它的时钟频率和它潜在的CPU缓存。但是它不可在不同的CPU间进行比较演示。

请参考百度百科和wiki百科

http://baike.baidu.com/view/1086713.htm

http://zh.wikipedia.org/zh-cn/BogoMips

Ok说了这么多,终于将该函数分析完了。

BogoMIPS与calibrate_delay的更多相关文章

  1. BogoMips 和cpu主频无关 不等于cpu频率

    http://tinylab.org/explore-linux-bogomips/ 内核探索:Linux BogoMips 探秘 Tao HongLiang 创作于 2015/05/12 打赏 By ...

  2. Android系统启动过程-uBoot+Kernel+Android

    摘要:本文是参考大量网上资源在结合自己查看源代码总结出来的,让自己同时也让大家加深对Android系统启动过程有一个更加深入的了解!再次强调,本文的大多数功劳应归功于那些原创者们,同时一些必要的参考链 ...

  3. init/main.c

    /* * linux/init/main.c * * Copyright (C) 1991, 1992 Linus Torvalds */ #include <stdarg.h> #inc ...

  4. 《Linux内核设计与实现》读书笔记(十一)- 定时器和时间管理【转】

    转自:http://www.cnblogs.com/wang_yb/archive/2013/05/10/3070373.html 系统中有很多与时间相关的程序(比如定期执行的任务,某一时间执行的任务 ...

  5. Linux內核中常用的一些延時方法

    Linux內核中常用的一些延時方法 這些方法在以下路徑下定義:kernel/include/linux/delay.h #ifndef _LINUX_DELAY_H #define _LINUX_DE ...

  6. Linux内核启动分析

    张超<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 我的代码可见https://www.shiyanlo ...

  7. 动静结合学内核:linux idle进程和init进程浅析

    刘柳 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 + titer1@qq.com 退休的贵族进程 ...

  8. 十天学Linux内核之第七天---电源开和关时都发生了什么

    原文:十天学Linux内核之第七天---电源开和关时都发生了什么 说实话感觉自己快写不下去了,其一是有些勉强跟不上来,其二是感觉自己越写越差,刚开始可能是新鲜感以及很多读者的鼓励,现在就是想快点完成自 ...

  9. Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3.0 ARMv7)

    http://blog.chinaunix.net/uid-20543672-id-3157283.html Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3 ...

随机推荐

  1. SEO-外部链接类型以及标准

    外部链接 外链的作用:宣传你的网站 相信大家都听过"内链为王,外链为皇"这句话,不管这句话对不对,从这句话上面,我们都能体会到外链的重要性. 外链类型: 1.博客 2.论坛 3.分 ...

  2. Struts1.x 环境搭建和技术准备(上)

    Struts 1.x 基于 Servlet,Struts 2.x基于Filter 1.servlet的注解配置方式和web.xml配置方式 使用servelt 3.0,eclipse在创建seb项目是 ...

  3. HTML5周记(二)

    大家好,很高兴又跟大家见面了!本周更新博主将给大家带来更精彩的HTML5技术分享,通过本周的学习,可实现大部分的网页制作.以下为本次更新内容. 第四章 css盒模型 <!DOCTYPE html ...

  4. 微信iOS客户端升级内核对自定义分享的影响

    上周,业务同学反应,公司的商品详情页,在有的Iphone手机上自定义分享信息失效.在自己手机上一直无法重现,在一个同事的手机上也重现了. 后来看到<微信iOS客户端将升级为WKWebview内核 ...

  5. 提问!同一ajax请求获取的图片路劲,在谷歌浏览器能正确展示图片,在火狐浏览器则显示路径undefined

    今天的工作学习之路遇见一个奇葩的问题,作为初级攻城狮的小生实在不知如何解决,都已经壁咚度娘一整天了,都未能解决问题,实属无奈,一开始认为是浏览器兼容的问题,但左看右看,也不是,也尝试过是不是页面加载与 ...

  6. 对于用div+css随心所欲布局的思考

    在div+css取代Table成为主流的时代,学会用其进行随心所欲的布局是一个不可回避的技能.那么,重点掌握哪几个要点呢? 整体布局:从整体到局部的顺序进行布局,逐步定义div集css样式: 灵活运用 ...

  7. iOS开发之左右抖动效果

    CAKeyframeAnimation *shakeAnim = [CAKeyframeAnimation animation]; shakeAnim.keyPath = @"transfo ...

  8. 【Egret】3d 服务器配置

    在服务器MIME里添加这些类型就可以了:

  9. Android中那些有你不知道的事

    在安卓开发中,总有那么一些看似简单,实则绊脚的难题,等你去探索,等你去解决,也许你已经遇见了解决了,也许你还没碰上,写下这篇总结,希望能帮助那行即将遇到的朋友,快速解决这些小问题! 一.activit ...

  10. Best Time to Buy and Sell Stock系列

    I题 Say you have an array for which the ith element is the price of a given stock on day i. If you we ...