Linux 内核跟踪点 API

作者:

Jason Baron

作者:

William Cohen

简介

跟踪点是位于内核中关键点的静态探测点。“探测器”通过回调机制向跟踪点注册/注销。这些“探测器”是严格类型化的函数,它们被传递由每个跟踪点定义的一组唯一参数。

通过这种简单的回调机制,“探测器”可用于分析、调试和理解内核行为。有许多工具提供了使用“探测器”的框架。这些工具包括 Systemtap、ftrace 和 LTTng。

跟踪点通过各种宏定义在多个头文件中。因此,本文档的目的是清晰地说明所有可用的跟踪点。其目的是不仅要了解哪些跟踪点可用,还要了解未来可能在何处添加跟踪点。

所呈现的 API 具有以下形式的函数:trace_tracepointname(function parameters)。这些是代码中随处可见的跟踪点回调。在 Documentation/trace/* 目录中介绍了在这些回调站点注册和注销探测点的内容。

IRQ

void trace_irq_handler_entry(int irq, struct irqaction *action)

在 irq 动作处理程序之前立即调用

参数

int irq

irq 号

struct irqaction *action

指向 struct irqaction 的指针

描述

action 指向的 struct irqaction 包含有关处理程序的各种信息,包括设备名称 action->name 和设备 ID action->dev_id。与 irq_handler_exit 跟踪点结合使用时,我们可以计算出 irq 处理程序的延迟。

void trace_irq_handler_exit(int irq, struct irqaction *action, int ret)

在 irq 动作处理程序返回后立即调用

参数

int irq

irq 号

struct irqaction *action

指向 struct irqaction 的指针

int ret

返回值

描述

如果 ret 值设置为 IRQ_HANDLED,则表示相应的 action->handler 已成功处理此 irq。否则,该 irq 可能是共享 irq 线,或者 irq 未成功处理。可与 irq_handler_entry 结合使用以了解 irq 处理程序的延迟。

void trace_softirq_entry(unsigned int vec_nr)

在 softirq 处理程序之前立即调用

参数

unsigned int vec_nr

softirq 向量号

描述

与 softirq_exit 跟踪点结合使用时,我们可以确定 softirq 处理程序例程。

void trace_softirq_exit(unsigned int vec_nr)

在 softirq 处理程序返回后立即调用

参数

unsigned int vec_nr

softirq 向量号

描述

与 softirq_entry 跟踪点结合使用时,我们可以确定 softirq 处理程序例程。

void trace_softirq_raise(unsigned int vec_nr)

当 softirq 被触发时立即调用

参数

unsigned int vec_nr

softirq 向量号

描述

与 softirq_entry 跟踪点结合使用时,我们可以确定 softirq 从触发到运行的延迟。

void trace_tasklet_entry(struct tasklet_struct *t, void *func)

在 tasklet 运行之前立即调用

参数

struct tasklet_struct *t

tasklet 指针

void *func

tasklet 回调或正在运行的函数

描述

用于查找单个 tasklet 的执行时间

void trace_tasklet_exit(struct tasklet_struct *t, void *func)

在 tasklet 运行后立即调用

参数

struct tasklet_struct *t

tasklet 指针

void *func

tasklet 回调或正在运行的函数

描述

用于查找单个 tasklet 的执行时间

信号

void trace_signal_generate(int sig, struct kernel_siginfo *info, struct task_struct *task, int group, int result)

当信号生成时调用

参数

int sig

信号编号

struct kernel_siginfo *info

指向 struct siginfo 的指针

struct task_struct *task

指向 struct task_struct 的指针

int group

共享或私有

int result

TRACE_SIGNAL_*

描述

当前进程将 ‘sig’ 信号与 ‘info’ siginfo 一起发送到 ‘task’ 进程。如果 ‘info’ 是 SEND_SIG_NOINFO 或 SEND_SIG_PRIV,则 ‘info’ 不是指针,您无法访问其字段。相反,SEND_SIG_NOINFO 表示 si_code 是 SI_USER,SEND_SIG_PRIV 表示 si_code 是 SI_KERNEL。

void trace_signal_deliver(int sig, struct kernel_siginfo *info, struct k_sigaction *ka)

当信号传递时调用

参数

int sig

信号编号

struct kernel_siginfo *info

指向 struct siginfo 的指针

struct k_sigaction *ka

指向 struct k_sigaction 的指针

描述

‘sig’ 信号与 ‘info’ siginfo 一起传递给当前进程,并将由 ‘ka’ 处理。ka->sa.sa_handler 可以是 SIG_IGN 或 SIG_DFL。请注意,signal_generate 跟踪点报告的某些信号可能会在到达此跟踪点之前丢失、被忽略或被修改(由调试器)。这意味着,这可以显示实际传递了哪些信号,但生成信号与传递信号的匹配可能不正确。

块 IO

void trace_block_touch_buffer(struct buffer_head *bh)

标记缓冲区已访问

参数

struct buffer_head *bh

正在访问的 buffer_head

描述

从 touch_buffer() 调用。

void trace_block_dirty_buffer(struct buffer_head *bh)

标记缓冲区脏

参数

struct buffer_head *bh

正在变脏的 buffer_head

描述

mark_buffer_dirty() 调用。

void trace_block_rq_requeue(struct request *rq)

将块 IO 请求放回队列

参数

struct request *rq

块 IO 操作请求

描述

块操作请求 rq 正在被放回队列 q。由于某种原因,该请求未完成,需要放回队列中。

void trace_block_rq_complete(struct request *rq, blk_status_t error, unsigned int nr_bytes)

设备驱动程序完成块 IO 操作

参数

struct request *rq

块操作请求

blk_status_t error

状态码

unsigned int nr_bytes

已完成字节数

描述

block_rq_complete 跟踪点事件表示设备驱动程序已完成操作请求的某个部分。如果 rq->bioNULL,则请求绝对没有额外的工作要做。如果 rq->bio 非空,则需要额外的工作来完成请求。

void trace_block_rq_error(struct request *rq, blk_status_t error, unsigned int nr_bytes)

设备驱动程序报告的块 IO 操作错误

参数

struct request *rq

块操作请求

blk_status_t error

状态码

unsigned int nr_bytes

已完成字节数

描述

block_rq_error 跟踪点事件表示设备驱动程序报告的操作请求的某个部分已失败。

void trace_block_rq_insert(struct request *rq)

将块操作请求插入队列

参数

struct request *rq

块 IO 操作请求

描述

在块操作请求 rq 插入队列 q 之前立即调用。可以检查操作请求 rq 结构中的字段,以确定待处理操作将访问哪个设备和扇区。

void trace_block_rq_issue(struct request *rq)

向设备驱动程序发出待处理的块 IO 请求操作

参数

struct request *rq

块 IO 操作请求

描述

当来自队列 q 的块操作请求 rq 被发送到设备驱动程序进行处理时调用。

void trace_block_rq_merge(struct request *rq)

将请求与调度器中的另一个请求合并

参数

struct request *rq

块 IO 操作请求

描述

当来自队列 q 的块操作请求 rq 与调度器中排队的另一个请求合并时调用。

void trace_block_io_start(struct request *rq)

插入一个请求以供执行

参数

struct request *rq

块 IO 操作请求

描述

当块操作请求 rq 排队等待执行时调用

void trace_block_io_done(struct request *rq)

块 IO 操作请求完成

参数

struct request *rq

块 IO 操作请求

描述

当块操作请求 rq 完成时调用

void trace_block_bio_complete(struct request_queue *q, struct bio *bio)

完成块操作的所有工作

参数

struct request_queue *q

持有块操作的队列

struct bio *bio

块操作已完成

描述

此跟踪点表明此块 IO 操作 bio 没有进一步的工作要做。

void trace_block_bio_backmerge(struct bio *bio)

将块操作合并到现有操作的末尾

参数

struct bio *bio

要合并的新块操作

描述

将块请求 bio 合并到现有块请求的末尾。

void trace_block_bio_frontmerge(struct bio *bio)

将块操作合并到现有操作的开头

参数

struct bio *bio

要合并的新块操作

描述

将块 IO 操作 bio 合并到现有块请求的开头。

void trace_block_bio_queue(struct bio *bio)

将新的块 IO 操作放入队列

参数

struct bio *bio

新块操作

描述

即将把块 IO 操作 bio 放入队列 q

void trace_block_getrq(struct bio *bio)

在队列中获取一个用于块 IO 操作的空闲请求条目

参数

struct bio *bio

待处理的块 IO 操作(可以是 NULL

描述

已分配一个请求结构来处理块 IO 操作 bio

void trace_block_plug(struct request_queue *q)

将操作请求保留在请求队列中

参数

struct request_queue *q

要阻塞的请求队列

描述

阻塞请求队列 q。不允许将块操作请求发送到设备驱动程序。相反,在队列中累积请求以提高块设备的吞吐量性能。

void trace_block_unplug(struct request_queue *q, unsigned int depth, bool explicit)

释放请求队列中的操作请求

参数

struct request_queue *q

要解除阻塞的请求队列

unsigned int depth

刚刚添加到队列中的请求数量

bool explicit

这是否是显式解除阻塞,还是来自 schedule() 的解除阻塞

描述

解除阻塞请求队列 q,因为设备驱动程序已安排处理请求队列中的元素。

void trace_block_split(struct bio *bio, unsigned int new_sector)

将单个 bio 结构拆分为两个 bio 结构

参数

struct bio *bio

正在拆分的块操作

unsigned int new_sector

新 bio 的起始扇区

描述

bio 请求 bio 需要拆分为两个 bio 请求。新创建的 bio 请求从 new_sector 开始。这种拆分可能是由于硬件限制(例如操作在 RAID 系统中跨越设备边界)而必需的。

void trace_block_bio_remap(struct bio *bio, dev_t dev, sector_t from)

将逻辑设备的请求映射到原始设备

参数

struct bio *bio

修订后的操作

dev_t dev

操作的原始设备

sector_t from

操作的原始扇区

描述

逻辑设备的某个操作已映射到原始块设备。

void trace_block_rq_remap(struct request *rq, dev_t dev, sector_t from)

映射块操作请求

参数

struct request *rq

块 IO 操作请求

dev_t dev

操作的设备

sector_t from

操作的原始扇区

描述

队列 q 中的块操作请求 rq 已重新映射。块操作请求 rq 包含当前信息,而 from 包含原始扇区。

工作队列

void trace_workqueue_queue_work(int req_cpu, struct pool_workqueue *pwq, struct work_struct *work)

当一个工作入队时调用

参数

int req_cpu

请求的 CPU

struct pool_workqueue *pwq

指向 struct pool_workqueue 的指针

struct work_struct *work

指向 struct work_struct 的指针

描述

此事件在工作立即入队时发生,或者在延迟工作实际入队到工作队列时(即:一旦达到延迟)发生。

void trace_workqueue_activate_work(struct work_struct *work)

当一个工作被激活时调用

参数

struct work_struct *work

指向 struct work_struct 的指针

描述

此事件在入队工作被放入活动队列时发生,这在入队后立即发生,除非达到 max_active 限制。

void trace_workqueue_execute_start(struct work_struct *work)

在工作队列回调之前立即调用

参数

struct work_struct *work

指向 struct work_struct 的指针

描述

允许跟踪工作队列的执行。

void trace_workqueue_execute_end(struct work_struct *work, work_func_t function)

在工作队列回调之后立即调用

参数

struct work_struct *work

指向 struct work_struct 的指针

work_func_t function

指向工作函数(worker function)的指针

描述

允许跟踪工作队列的执行。