Linux 内核跟踪点 API

作者:

Jason Baron

作者:

William Cohen

简介

跟踪点是位于内核中战略位置的静态探测点。“探测器”通过回调机制在跟踪点注册/注销。“探测器”是严格类型的函数,它们传递由每个跟踪点定义的一组独特的参数。

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

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

提供的 API 具有以下形式的函数:trace_tracepointname(函数 参数)。这些是在整个代码中找到的跟踪点回调。在这些回调站点注册和注销探测器在 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 的执行时间

SIGNAL

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_*

描述

当前进程使用“info”siginfo 向“task”进程发送一个“sig”信号。如果“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 跟踪点报告的一些信号可能会丢失、被忽略或被(调试器)修改,然后才到达此跟踪点。这意味着,这可以显示实际传递了哪些信号,但匹配生成的信号和传递的信号可能不正确。

块 I/O

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)

将块 I/O 请求放回队列

参数

struct request *rq

块 I/O 操作请求

描述

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

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

块 I/O 操作由设备驱动程序完成

参数

struct request *rq

块操作请求

blk_status_t error

状态码

unsigned int nr_bytes

已完成的字节数

描述

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

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

设备驱动程序报告的块 I/O 操作错误

参数

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

块 I/O 操作请求

描述

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

void trace_block_rq_issue(struct request *rq)

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

参数

struct request *rq

块 I/O 操作请求

描述

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

void trace_block_rq_merge(struct request *rq)

将请求与电梯中的另一个请求合并

参数

struct request *rq

块 I/O 操作请求

描述

当队列 q 中的块操作请求 rq 被合并到电梯中排队的另一个请求时调用。

void trace_block_io_start(struct request *rq)

插入一个要执行的请求

参数

struct request *rq

块 I/O 操作请求

描述

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

void trace_block_io_done(struct request *rq)

块 I/O 操作请求完成

参数

struct request *rq

块 I/O 操作请求

描述

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

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

完成块操作的所有工作

参数

struct request_queue *q

保存块操作的队列

struct bio *bio

已完成的块操作

描述

此跟踪点指示此块 I/O 操作 bio 没有进一步的工作要做。

void trace_block_bio_bounce(struct bio *bio)

处理块操作时使用了反弹缓冲区

参数

struct bio *bio

块操作

描述

使用反弹缓冲区来处理 q 中的块操作 bio。当硬件限制阻止 bio 数据存储区和 I/O 设备之间直接传输数据时,会发生这种情况。使用反弹缓冲区需要额外的数据复制,并会降低性能。

void trace_block_bio_backmerge(struct bio *bio)

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

参数

struct bio *bio

要合并的新块操作

描述

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

void trace_block_bio_frontmerge(struct bio *bio)

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

参数

struct bio *bio

要合并的新块操作

描述

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

void trace_block_bio_queue(struct bio *bio)

将新的块 I/O 操作放入队列

参数

struct bio *bio

新的块操作

描述

即将将块 I/O 操作 bio 放入队列 q

void trace_block_getrq(struct bio *bio)

为块 I/O 操作获取队列中的一个空闲请求条目

参数

struct bio *bio

待处理的块 I/O 操作(可以为 NULL

描述

已分配一个请求结构体来处理块 I/O 操作 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

块 I/O 操作请求

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

指向结构体 pool_workqueue 的指针

struct work_struct *work

指向结构体 work_struct 的指针

描述

当一个工作立即排队或者当一个延迟的工作实际上在工作队列上排队时(即:一旦达到延迟时间)会发生此事件。

void trace_workqueue_activate_work(struct work_struct *work)

当一个工作被激活时调用

参数

struct work_struct *work

指向结构体 work_struct 的指针

描述

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

void trace_workqueue_execute_start(struct work_struct *work)

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

参数

struct work_struct *work

指向结构体 work_struct 的指针

描述

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

void trace_workqueue_execute_end(struct work_struct *work, work_func_t function)

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

参数

struct work_struct *work

指向结构体 work_struct 的指针

work_func_t function

指向工作函数的指针

描述

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