linux calibrate_delay

本文详细解析了Linux内核启动过程中的BogoMIPS计算原理,介绍了calibrate_delay()函数如何通过循环指令估算CPU速度,揭示了BogoMIPS值的计算核心函数及其算法细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://blog.youkuaiyun.com/chenliang0224/article/details/78704823
1.内核启动信息

console [ttyS0] enabled
Calibrating delay loop… 148.88 BogoMIPS (lpj=744448)
pid_max: default: 32768 minimum: 301

2.BogoMIPS

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

3.calibrate_delay()

路径:linux-3.10.x\init\main.c–>start_kernel–>calibrate_delay

void __cpuinit calibrate_delay(void)
{
unsigned long lpj;
static bool printed;
int this_cpu = smp_processor_id();

if (per_cpu(cpu_loops_per_jiffy, this_cpu)) {
	lpj = per_cpu(cpu_loops_per_jiffy, this_cpu);
	if (!printed)
		pr_info("Calibrating delay loop (skipped) "
			"already calibrated this CPU");
} else 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_is_known())) {
	;
} else if ((lpj = calibrate_delay_direct()) != 0) {
	if (!printed)
		pr_info("Calibrating delay using timer "
			"specific routine.. ");
} else {
	if (!printed)
		pr_info("Calibrating delay loop... ");
	lpj = calibrate_delay_converge();
}
per_cpu(cpu_loops_per_jiffy, this_cpu) = lpj;
if (!printed)
	pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
		lpj/(500000/HZ),
		(lpj/(5000/HZ)) % 100, lpj);

loops_per_jiffy = lpj;
printed = true;

}
BogoMIPS计算的核心函数:

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);	//1<<12=4096

/* wait for "start of" clock tick */
ticks = jiffies;
while (ticks == jiffies)	//等待下一个时钟节拍
	; /* nothing */
/* Go .. */
ticks = jiffies;
do {
	if (++trial_in_band == (1<<band)) {	//首次进入do{...}while(x)时if条件成立,初始化band=1和trial_in_band=0
		++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;	//去除上面do{...}while(x)里循环的最后一次,因为最后一次时钟节拍已经变更,所以不能统计到里面
loopadd_base = lpj * band; //上面do{...}while(x)最后一次循环所需的时间,也是下一个时钟节拍的起始值
lpj_base = lpj * trials; //一个时钟节拍需要的时间

recalibrate:
lpj = lpj_base; //一个时钟节拍需要的时间
loopadd = loopadd_base; //上面do{…}while(x)最后一次循环所需的时间,也是下一个时钟节拍的起始值

/*
 * Do a binary approximation to get lpj set to
 * equal one clock (up to LPS_PREC bits)
 */
chop_limit = lpj >> LPS_PREC; //用于控制循环计算的次数,一个时钟节拍分频/2^8, 2^8=256
while (loopadd > chop_limit) { //采用二分法的方式,无限靠近真值, 下一个时钟节拍的首次值 > 一个时钟节拍内256分频后的值,通过分析该while循环意思应该是要循环256次
	lpj += loopadd;
	ticks = jiffies;
	while (ticks == jiffies)
		; /* nothing */
	ticks = jiffies;
	__delay(lpj);
	if (jiffies != ticks)	/* longer than 1 tick */
		lpj -= loopadd; //时钟滴答切换,徐去除最后一次值,这里的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;

}

根据报文中lpj=744448,Calibrating delay loop… 148.88 BogoMIPS (lpj=744448)

作者:chenliang0224
来源:优快云
原文:https://blog.youkuaiyun.com/chenliang0224/article/details/78704823
版权声明:本文为博主原创文章,转载请附上博文链接!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值