当前位置: 首页 > news >正文

Linux ioc_timer_fn iocost定时器与hweight更新

Linux ioc_timer_fn iocost定时器与hweight更新

ioc_timer_fn是iocost控制器的周期性定时器处理函数,它以固定间隔(默认为64ms)执行,负责iocost的多个核心维护任务:更新iocg的hweight(层级权重)、调整I/O带宽配额、处理过期的等待队列以及触发成本模型的重新校准。该定时器是iocost状态机运转的节拍器。

定时器初始化与调度

iocost定时器在ioc结构体初始化时通过timer_setup注册,每次到期后根据系统负载情况自适应调整下次触发时间。

```c
static void ioc_timer_fn(struct timer_list *timer)
{
struct ioc *ioc = from_timer(ioc, timer, timer);
struct ioc_gq *iocg;
unsigned long expires;
u64 now, next, vtime;
int nr_shortages = 0, nr_lagging = 0;
LIST_HEAD(hlist);

now = ktime_get();
vtime = now - ioc->period;

/*
* 检查当前周期是否结束,若结束则重置周期计数器
* 并刷新全局vtime基准
*/
if (vtime > ioc->period_us * NSEC_PER_USEC) {
ioc->period += ioc->period_us;
vtime = now - ioc->period;
ioc->vtime_base += ioc->period_us * ioc->vtime_rate / 100;
}

/*
* 遍历所有iocg,更新其hweight、检查是否缺乏
* quota或处于滞后状态
*/
list_for_each_entry(iocg, &ioc->active_iocgs, active_list) {
u64 hweight, usage;
bool shortage = false;

/*
* hweight的层级更新:根据iocg在cgroup树中的
* 位置和其子节点权重重新分配当前层的权重
*/
hweight = iocg->weight;
if (iocg->level > 0) {
struct ioc_gq *parent = iocg->parent;
if (parent && parent->child_weights)
hweight = parent->hweight * iocg->weight
/ parent->child_weights;
}

iocg->hweight = hweight;

/*
* 计算该iocg的实际使用率(usage),
* 用于后续quota调整决策
*/
usage = iocg->usage_delta * USEC_PER_SEC
/ (now - iocg->usage_timestamp);
iocg->usage_timestamp = now;
iocg->usage_delta = 0;

/*
* 如果usage超过配置的限额,标记为短缺
*/
if (usage > iocg->max_usage) {
shortage = true;
nr_shortages++;
}
}
```

hweight层级权重计算

hweight(hierarchical weight)是iocost实现层级I/O带宽分配的核心概念。每个iocg的hweight由其父节点的hweight和自身在兄弟节点中的权重占比共同决定,确保cgroup树中每一层的带宽分配符合预期比例。

```c
static void ioc_refresh_hweights(struct ioc *ioc)
{
struct ioc_gq *iocg;
u64 total_child_weight = 0;

/*
* 第一遍扫描:统计每个iocg的子节点总权重,
* 如果子节点没有设置权重,则继承父节点权重
*/
list_for_each_entry(iocg, &ioc->active_iocgs, active_list) {
struct ioc_gq *child;
u64 child_weight = 0;

list_for_each_entry(child, &iocg->children, sibling_list) {
child_weight += child->weight;
}

iocg->child_weights = child_weight ?: iocg->weight;
}

/*
* 第二遍扫描:自顶向下计算hweight。
* 根iocg的hweight为1.0(用固定点表示法)
*/
list_for_each_entry(iocg, &ioc->active_iocgs, active_list) {
if (iocg->parent) {
u64 sibling_total = iocg->parent->child_weights;
if (sibling_total)
iocg->hweight = iocg->parent->hweight * iocg->weight
/ sibling_total;
else
iocg->hweight = iocg->parent->hweight;
} else {
iocg->hweight = HWEIGHT_ONE; /* 根节点 */
}
}
}
```

quota分配与vtime预算

定时器处理函数还负责基于hweight为每个iocg分配I/O时间预算(vtime)。vtime是iocost中衡量I/O资源消耗的虚拟时间单位。

```c
static void ioc_distribute_vtime(struct ioc *ioc, struct list_head *hlist)
{
struct ioc_gq *iocg, *tiocg;
u64 vtime, total_hweight = 0;
u64 vtime_per_cycle;

vtime_per_cycle = ioc->period_us * ioc->vtime_rate / 100;

/*
* 统计所有活跃iocg的hweight总和
*/
list_for_each_entry(iocg, hlist, hweight_list) {
total_hweight += iocg->hweight;
}

if (!total_hweight)
return;

/*
* 根据每个iocg的hweight占比分配vtime预算:
* vtime_budget = vtime_per_cycle * iocg->hweight / total_hweight
*/
list_for_each_entry(iocg, hlist, hweight_list) {
u64 budget = vtime_per_cycle * iocg->hweight / total_hweight;

iocg->vtime_budget += budget;

/*
* 如果iocg的vtime消耗已经超过预算,
* 将其加入延迟队列以限制I/O
*/
if (iocg->vtime_used > iocg->vtime_budget) {
iocg->debt = iocg->vtime_used - iocg->vtime_budget;
iocg->vtime_budget = 0;
}
}
}
```

定时器重调度

在所有维护工作完成后,ioc_timer_fn根据当前系统负载和iocg的短缺情况调整下次定时器触发的间隔。

```c
/*
* 根据短缺和滞后情况决定下次调度间隔
*/
if (nr_shortages) {
/*
* 如果存在短缺,缩短间隔以更快响应
*/
expires = msecs_to_jiffies(IOC_TIMER_INTERVAL_MS / 2);
} else if (nr_lagging) {
expires = msecs_to_jiffies(IOC_TIMER_INTERVAL_MS * 3 / 4);
} else {
expires = msecs_to_jiffies(IOC_TIMER_INTERVAL_MS);
}

mod_timer(&ioc->timer, jiffies + expires);

out_unlock:
spin_unlock_irq(&ioc->lock);
}
```

通过ioc_timer_fn的定期执行,iocost实现了对块I/O资源的动态调度——hweight机制保证了cgroup间按比例分配带宽,vtime预算控制防止了单个cgroup过度使用I/O资源,自适应定时器间隔则在高负载时提供更快的响应。

http://www.jsqmd.com/news/1003921/

相关文章:

  • 虚拟化软件替代方案:如何在3个步骤内找到最适合你的开源解决方案?
  • 2026年台州杭州岗亭选购指南:区域服务、技术适配与行业趋势深度分析 - 优质品牌商家
  • 2026年北京公司注册代理机构综合能力分析:服务范围、团队经验与真实案例解读 - 优质品牌商家
  • 2026河北油管厂家排行揭秘,这样选才不踩坑
  • 六盘水余生黄金回收实测 2026卖金价格指南 - 余生黄金回收
  • Cadence Virtuoso IC 618版图新手避坑:从DRC/LVS报错到电源环(Guard Ring)的正确画法
  • 吐血整理!支付宝小程序从“搜不到”到“排第一”的秘诀
  • 世界从来不是单一逻辑的产物,而是“可推导的骨架”与“不可推导的血肉”共同编织的复合体。
  • IC697BEM731Z控制器模块
  • 告别卡顿!在Uni-app里用海康H5Player播放WS视频流,保姆级接入教程(含RenderJS避坑)
  • 女性生理期健康护理常识:科学认知与日常养护建议
  • STM32F103ZE精英板ADC多路电压采集工程(含双电机实时监测与LCD显示)
  • 2026年你必须知道的5种DeFi智能合约漏洞——从100个真实案例看资产安全
  • 终极指南:如何使用Waifu2x-Extension-GUI让模糊图片视频变高清
  • 5分钟快速搭建OBS局域网直播系统:obs-rtspserver完全指南
  • 寄快递哪个平台最便宜?2026全网寄件渠道省钱对比 - 快递物流资讯
  • 如何让微信网页版重新可用:wechat-need-web技术方案深度解析
  • WinForm下可交互SVG图形控件:支持标注定位、元素锁定与操作回退
  • 从Arduino到ESP32:手把手教你调试I2C通信,搞定‘地址无响应’和波形毛刺
  • 计算机毕业设计之基于Python的校园书院预约系统的设计与实现
  • 保姆级教程:用Python一键下载处理CTU-13僵尸网络检测数据集(附完整代码)
  • Linux iocost_model校准权重与线性回归参数
  • 2026年江阴装修公司口碑观察:从设计到落地,这些企业值得关注(含无锡/苏州/张家港) - 优质品牌商家
  • 2026最新|别再花冤枉钱降重!亲测DeepSeek免费洗稿指令+4大工具,稳降至AIGC安全线 - 降AI实验室
  • 3分钟快速上手:语雀文档批量导出工具完全指南
  • 别被“国家需要”忽悠!网络空间安全专业真实就业指南|建议收藏学习
  • 中国多时期生态系统类型空间分布数据(1980–2020年)|7大生态系统分类
  • ArcGIS Pro 3.0 保姆级教程:三步搞定地形剖面图,附送练习DEM数据包
  • 从开箱到跑通Demo:EdgeBoard FZ5赛事卡上手实录(含系统烧录避坑与资源包整理)
  • pytest-flask:简化 Flask 应用测试流程