Linux irqtime_account_process_tick中断时间计费irqtime_account_process_tick是Linux内核中负责统计中断消耗CPU时间的核心函数定义在kernel/sched/cputime.c。它精确记录每个CPU在处理硬中断hardirq和软中断softirq上花费的时间这些数据通过/proc/stat和task_statm暴露给用户空间也是调度器进行负载均衡的依据。函数原型cstatic void irqtime_account_process_tick(struct task_struct *p, int user_tick,struct rq *rq, int ticks)其中p是当前进程user_tick表示本次tick是否在用户态rq是当前CPU的运行队列ticks是统计的tick数量通常为1。核心实现cstatic void irqtime_account_process_tick(struct task_struct *p, int user_tick,struct rq *rq, int ticks){s64 delta;struct irqtime *irqtime this_cpu_ptr(cpu_irqtime);if (!irqtime-stolen) {irqtime-stolen 1;return;}if (irqtime-hardirq_time) {delta irqtime-hardirq_time - irqtime-hardirq_start;if (delta 0) {account_steal_time(delta);irqtime-hardirq_start irqtime-hardirq_time;}}if (irqtime-softirq_time) {delta irqtime-softirq_time - irqtime-softirq_start;if (delta 0) {account_steal_time(delta);irqtime-softirq_start irqtime-softirq_time;}}if (user_tick)account_user_time(p, cputime_one_jiffy, cputime_one_jiffy);else if ((p ! rq-idle) (irqtime-hardirq_time || irqtime-softirq_time))account_system_time(p, HARDIRQ_OFFSET, cputime_one_jiffy);elseaccount_idle_time(cputime_one_jiffy);}irqtime机制的核心是per-CPU变量cpu_irqtime定义如下cstruct irqtime {u64 hardirq_time;u64 softirq_time;u64 hardirq_start;u64 softirq_start;int stolen;};hardirq_time记录了该CPU自系统启动以来累计的硬中断服务时间由account_system_time在每次中断处理结束后递增。softirq_time同理。这两个计数器通过sched_clock或sched_clock_cpu提供的高精度时间戳累加。irqtime_account_process_tick在每个tick中断时被调用通常频率为100Hz或250Hz。它通过比较当前中断累计时间与上一次tick记录值的差值计算出该tick内花在中断处理上的时间。delta为正说明该tick至少有一部分时间消耗在中断处理中。关键路径上的入口函数为account_process_tickcvoid account_process_tick(struct task_struct *p, int user_tick){cputime_t one_jiffy jiffies_to_cputime(1);struct rq *rq this_rq();if (sched_clock_irqtime) {irqtime_account_process_tick(p, user_tick, rq, 1);return;}if (user_tick)account_user_time(p, one_jiffy, one_jiffy);else if ((p ! rq-idle) (irq_count() HARDIRQ_OFFSET))account_system_time(p, HARDIRQ_OFFSET, one_jiffy);elseaccount_idle_time(one_jiffy);}当sched_clock_irqtime被配置且体系结构支持时启用irqtime_account_process_tick的精准路径。否则回退到传统的粗粒度统计检查irq_count()是否为HARDIRQ_OFFSET来判断当前是否在硬中断上下文。hardirq_time和softirq_time的更新发生在中断处理的出入口cvoid account_system_time(struct task_struct *p, int index, cputime_t cputime){struct irqtime *irqtime this_cpu_ptr(cpu_irqtime);if (index HARDIRQ_OFFSET) {irqtime-hardirq_time cputime;irqtime-hardirq_start irqtime-hardirq_time;} else if (index SOFTIRQ_OFFSET) {irqtime-softirq_time cputime;irqtime-softirq_start irqtime-softirq_time;}...}这个函数在update_process_times中被调用而update_process_times由tick_periodic或tick_sched_handle触发。irqtime_account_process_tick中的steal字段处理虚拟化场景中的steal time。当hypervisor窃取分配给guest的CPU时间时stolen标记防止虚报中断时间。在KVM中steal time通过kvm_steal_clock更新irqtime检查该字段后跳过已盗用的时间片。irqtime数据通过/proc/stat的intr行和softirq行暴露cstatic int show_stat(struct seq_file *p, void *v){...for_each_online_cpu(i) {struct irqtime *irqtime per_cpu_ptr(cpu_irqtime, i);seq_printf(p, cpu%d ..., i);seq_printf(p, ... %llu %llu,irqtime-hardirq_time,irqtime-softirq_time);}...}irqtime_account_process_tick也影响调度器的负载均衡决策。当某个CPU大量时间消耗在中断处理中其irqtime占比高说明该CPU不适合再分配新的计算或IO任务。调度器的find_idlest_cpu在选择目标CPU时会参考该CPU的空闲时间而irqtime未被正确记录时可能导致CPU被过度分配给中断密集型任务。CONFIG_IRQ_TIME_ACCOUNTING是使能该功能的编译选项。如果未配置此选项内核回退到tick级别的粗粒度统计无法精确区分中断时间和进程时间。在实时内核RT中irqtime是sched_rt_runtime_exceeded检测的关键输入因为它影响实时任务的运行时间预算计算。
Linux irqtime_account_process_tick中断时间计费
发布时间:2026/6/15 0:43:50
Linux irqtime_account_process_tick中断时间计费irqtime_account_process_tick是Linux内核中负责统计中断消耗CPU时间的核心函数定义在kernel/sched/cputime.c。它精确记录每个CPU在处理硬中断hardirq和软中断softirq上花费的时间这些数据通过/proc/stat和task_statm暴露给用户空间也是调度器进行负载均衡的依据。函数原型cstatic void irqtime_account_process_tick(struct task_struct *p, int user_tick,struct rq *rq, int ticks)其中p是当前进程user_tick表示本次tick是否在用户态rq是当前CPU的运行队列ticks是统计的tick数量通常为1。核心实现cstatic void irqtime_account_process_tick(struct task_struct *p, int user_tick,struct rq *rq, int ticks){s64 delta;struct irqtime *irqtime this_cpu_ptr(cpu_irqtime);if (!irqtime-stolen) {irqtime-stolen 1;return;}if (irqtime-hardirq_time) {delta irqtime-hardirq_time - irqtime-hardirq_start;if (delta 0) {account_steal_time(delta);irqtime-hardirq_start irqtime-hardirq_time;}}if (irqtime-softirq_time) {delta irqtime-softirq_time - irqtime-softirq_start;if (delta 0) {account_steal_time(delta);irqtime-softirq_start irqtime-softirq_time;}}if (user_tick)account_user_time(p, cputime_one_jiffy, cputime_one_jiffy);else if ((p ! rq-idle) (irqtime-hardirq_time || irqtime-softirq_time))account_system_time(p, HARDIRQ_OFFSET, cputime_one_jiffy);elseaccount_idle_time(cputime_one_jiffy);}irqtime机制的核心是per-CPU变量cpu_irqtime定义如下cstruct irqtime {u64 hardirq_time;u64 softirq_time;u64 hardirq_start;u64 softirq_start;int stolen;};hardirq_time记录了该CPU自系统启动以来累计的硬中断服务时间由account_system_time在每次中断处理结束后递增。softirq_time同理。这两个计数器通过sched_clock或sched_clock_cpu提供的高精度时间戳累加。irqtime_account_process_tick在每个tick中断时被调用通常频率为100Hz或250Hz。它通过比较当前中断累计时间与上一次tick记录值的差值计算出该tick内花在中断处理上的时间。delta为正说明该tick至少有一部分时间消耗在中断处理中。关键路径上的入口函数为account_process_tickcvoid account_process_tick(struct task_struct *p, int user_tick){cputime_t one_jiffy jiffies_to_cputime(1);struct rq *rq this_rq();if (sched_clock_irqtime) {irqtime_account_process_tick(p, user_tick, rq, 1);return;}if (user_tick)account_user_time(p, one_jiffy, one_jiffy);else if ((p ! rq-idle) (irq_count() HARDIRQ_OFFSET))account_system_time(p, HARDIRQ_OFFSET, one_jiffy);elseaccount_idle_time(one_jiffy);}当sched_clock_irqtime被配置且体系结构支持时启用irqtime_account_process_tick的精准路径。否则回退到传统的粗粒度统计检查irq_count()是否为HARDIRQ_OFFSET来判断当前是否在硬中断上下文。hardirq_time和softirq_time的更新发生在中断处理的出入口cvoid account_system_time(struct task_struct *p, int index, cputime_t cputime){struct irqtime *irqtime this_cpu_ptr(cpu_irqtime);if (index HARDIRQ_OFFSET) {irqtime-hardirq_time cputime;irqtime-hardirq_start irqtime-hardirq_time;} else if (index SOFTIRQ_OFFSET) {irqtime-softirq_time cputime;irqtime-softirq_start irqtime-softirq_time;}...}这个函数在update_process_times中被调用而update_process_times由tick_periodic或tick_sched_handle触发。irqtime_account_process_tick中的steal字段处理虚拟化场景中的steal time。当hypervisor窃取分配给guest的CPU时间时stolen标记防止虚报中断时间。在KVM中steal time通过kvm_steal_clock更新irqtime检查该字段后跳过已盗用的时间片。irqtime数据通过/proc/stat的intr行和softirq行暴露cstatic int show_stat(struct seq_file *p, void *v){...for_each_online_cpu(i) {struct irqtime *irqtime per_cpu_ptr(cpu_irqtime, i);seq_printf(p, cpu%d ..., i);seq_printf(p, ... %llu %llu,irqtime-hardirq_time,irqtime-softirq_time);}...}irqtime_account_process_tick也影响调度器的负载均衡决策。当某个CPU大量时间消耗在中断处理中其irqtime占比高说明该CPU不适合再分配新的计算或IO任务。调度器的find_idlest_cpu在选择目标CPU时会参考该CPU的空闲时间而irqtime未被正确记录时可能导致CPU被过度分配给中断密集型任务。CONFIG_IRQ_TIME_ACCOUNTING是使能该功能的编译选项。如果未配置此选项内核回退到tick级别的粗粒度统计无法精确区分中断时间和进程时间。在实时内核RT中irqtime是sched_rt_runtime_exceeded检测的关键输入因为它影响实时任务的运行时间预算计算。