Linux0.11 BADNESS宏分析
BADNESS宏主要在getblk函数中使用,用于获取一个进可能开销小的缓冲区
定义
#define BADNESS(bh) (((bh)->b_dirt<<1)+(bh)->b_lock)
通过以上的宏可以看出
- 一个b_dirt和b_lock的缓冲区开销最大
- 其次是一个b_dirt的缓冲区
- 再次是一个b_lock的缓冲区
- 最后是一个既干净又未锁定的缓冲区
代码片段如下
repeat:
/*
* 先根据dev和block在高速缓存hash表中获取,如果存在直接返回
*/
if ((bh = get_hash_table(dev, block)))
return bh;
/*
* tmp指向缓冲区头部
* 下面的代码意思是需要找到一个b_count为0的高速缓存
* 一直对BANDNESS不理解,再次解释一下
*
* BANDNESS = bh->b_dirt*2 + bh->b_lock
* 分析如下
*
* 从free_list开始遍历
* 第一次的时候bh为空因此可以进入if (!bh || BADNESS(tmp) < BADNESS(bh))
* 将从free_list找到的可用tmp赋值为bh
* 如果此bh的lock和dirt都为0,则直接可以用这个bh,否则继续进入循环
* 此时又找到一个tmp,然后利用BADNESS宏进行对比
* 可以发现系统倾向于选择一个lock和dirt都为0的缓冲区,如果实在找不到
* 那就选择一个lock置位的,最后如果实在找不到那就找一个lock和dirt都为1的
* 如果所有的b_count都在用,则睡眠一会在重新查找
* BADNESS值越小表示使用该块的系统开销越小,优先选择该块。
* 是否标记dirt对BADNES的计算结果有很大影响。
* 如果块既“未锁定”又是“干净的”,则可以使用直接退出循环
*/
tmp = free_list;
do {
if (tmp->b_count)
continue;
/*
* 如果bh为空,第一次肯定为空
*/
if (!bh || BADNESS(tmp) < BADNESS(bh)) {
bh = tmp;
if (!BADNESS(tmp))
break;
}
/* and repeat until we find something good */
} while ((tmp = tmp->b_next_free) != free_list);
/*
* 如果没有找到,则睡眠一会儿,然后继续找
*/
if (!bh) {
sleep_on(&buffer_wait);
goto repeat;
}
/*
* 根据上面的BADNESS分析,获取的缓冲区如果上锁,需求等待解锁
* wait_on_buffer会引起任务切换,因此需要再次检查该缓冲区的使用情况
*
*/
wait_on_buffer(bh);
if (bh->b_count)
goto repeat;
/*
* 如果该缓冲区已经被修改,则需要和磁盘进行同步并等待该缓冲区解锁
*
*/
while (bh->b_dirt) {
sync_dev(bh->b_dev);
wait_on_buffer(bh);
if (bh->b_count)
goto repeat;
}
浙公网安备 33010602011771号