1. 介绍
tracepoint为我们trace 内核event提供了钩子函数,我们可以通过tracepoint追踪内核事件。
tracepoint详细介绍:https://blog.csdn.net/geshifei/article/details/94360470
2.使用tracepoint统计IRQ频繁发生的次数,以及打印每次IRQ所用的时间。
思路:创建一个数组,数组中每个成员都是int型,用来统计对应IRQ的发生次数。
a. 首先,定义要保存的irq计数次数的结构体。
struct irq_state{ int irq_count[NR_IRQS]; ktime_t irq_time_stamp[NR_IRQS]; }
b. 使用tracepoint,可以让我们每次进入某个IRQ时,都先进钩子函数,所以,在这里可以统计IRQ发生的次数。
void irq_handler_entry_probe(void *data, int irq, struct irqaction *action) { struct irq_state * irqs; if (action && (action->flags & IRQF_PERCPU)) //只关注SPI
reuturn;
irqs = this_cpu_ptr(data);
global_time = ktime_get();
irqs->irq_count[irq] ++;
//记录1000次irq的时间间隔
if (irqs->irq_count[irq] > 1000){
pr_notice("the irq=%d was entry 1000 times, take %lld ms. ", irq, ktime_get() - irqs->irq_time_stamp[irq]);
irqs->irq_count[irq] = 0;
irqs->irq_time_stamp[irq] = ktime_get(); //记录进入irq的时间
}
}
c. 再写一个irq退出的函数,可以用来统计每个irq中执行的时间。
void irq_handler_exit_probe(void *data, int irq, struct irqaction *action, int res) { strcut irq_state *irqs; //irqs = this_cpu_ptr(data); pr_notice("the irq=%d action time is %lld. ",irq, ktime_get() - global_time);
global_time = 0; }
d. 写一个kernel model,在init函数中连接钩子函数并分配cpu memory。
static int __init irq_count_init()
{ irq_state = alloc_percpu(struct irq_state); ret = register_trace_irq_handler_entry(irq_handler_entry_probe, irq_state); ret = register_trace_irq_handler_exit(irq_handler_exit_probe, irq_state);
}