请考虑订阅LWN 订阅是LWN.net的生命线。 如果您喜欢这些内容,并希望看到更多的内容,您的订阅将有助于确保LWN继续蓬勃发展。 请访问此页面加入我们,让LWN继续在网络上传播。 |
内核的跟踪基础架构被设计为快速,并尽可能少地干扰系统的正常运行。 这一要求的一个结果是,当跟踪点被命中时,运行的代码不能休眠;否则,跟踪点的执行可能会对内核真正工作的执行造成任意延迟。 尽管有延迟,但有时在tracepoint中睡眠的能力还是很方便的。 Michael Jeanson的 可睡眠跟踪点补丁集为(某些)跟踪点处理程序在执行任务时小睡一下提供了条件,但目前还没有完成这项工作。
在内核中,跟踪机制不需要睡觉;它的任务通常是打包与给定跟踪点相关的数据,并将结果放入环形缓冲区,以便传输到用户空间。 因此,推动可休眠跟踪点的用例必须来自其他地方--尤其是来自用户空间连接到跟踪点的 BPF 程序。 这些程序目前仅限于访问内核空间的数据,而访问内核空间的数据无需休眠即可完成。 不过,在跟踪点处理程序中查看用户空间数据的能力也很有价值。 当处理程序试图访问这些数据时,并不能保证这些数据驻留在RAM中;如果这些数据不存在,就会导致页面故障。 处理页面故障可能会花费任意多的时间,在此期间,故障进程必须进入休眠状态。
在当前的内核中,这种可能性阻止了跟踪点处理程序对用户空间数据的访问。 具体地说,它意味着跟踪点不能对从用户空间传递过来的指针进行反引用。 因此,例如,在进入openat2()系统调用时运行的跟踪点可以看到用户空间传递过来的open_how结构的指针,但是不能检查结构本身的内容。
tracepoints本身并没有使睡眠成为不可能--至少,对于那些在内核不在原子上下文中运行时执行的tracepoints来说是这样。 但是BPF子系统长期以来一直有自己的规则,即BPF程序不能休眠。 不过,这将在5.10内核中改变,这要归功于可休眠BPF程序的加入,它不再受此限制。 只有特定类型的BPF程序才允许阻塞;在5.10内核中,跟踪程序也在此列。 不过,在 5.10 版本中将不会有用户使用这一功能。
Jeanson的补丁集为增加这样的用户奠定了基础,建立了支持将可休眠BPF程序附加到特定跟踪点的基础架构。 必须小心支持这种能力,因为如上所述,内核经常运行在休眠是个坏主意的环境中。 具体来说,可休眠BPF程序只能附加到位于允许休眠的代码区域中的tracepoint。
没有办法自动知道给定的tracepoint是否可以安全休眠,因此现有的tracepoint在没有明确修改的情况下不允许附加可休眠BPF程序。 Jeanson的补丁集增加了一个名为TRACE_EVENT_FN_MAYSLEEP ()的新宏, 作为TRACE_EVENT_FN()的一个变体, 它定义了一个具有相关注册和取消注册函数的跟踪点。 将现有的跟踪点切换到新的宏, 表明在那里附加可睡眠程序是安全的。
这些宏中最重要的变化是,如果一个跟踪点被标记为接受可休眠程序,那么当该跟踪点被命中时调用的跟踪器将在启用抢占的情况下运行。 这是能够处理页面故障的必要先决条件,但它也改变了所有这些跟踪器的编写预期。 跟踪器本身将需要修改,以便在启用抢占的情况下安全运行 - 这项工作尚未发布。 目前,补丁集通过修改 ftrace、perf 和 BPF 跟踪器来处理这种情况,在内部明确禁用抢占,从而避免任何不幸的意外。
如上所述,推动这项工作的用例是跟踪从用户空间传递到系统调用的指针。 Jeanson的补丁集修改了系统调用的入口和出口跟踪点,使其使用TRACE_EVENT_FN_MAYSLEEP(),从而为可休眠程序的附着创造了条件,这些程序可以在用户空间内存中翻找以响应系统调用。
在这一点上只缺少一个部分:实际修复跟踪器并使用新的基础架构来附加和运行可休眠的BPF程序。 正如补丁集的封面信所指出的那样:
这似乎是一个奇怪的地方,就在让所有东西都实际工作之前,但此时的改变可能会对后续补丁产生重大影响。
根据目前的讨论,似乎没有必要在代码的这个级别上做大的改动;大多数意见都与边缘的细节有关。 如果这种情况保持不变,我们应该期待在不久的将来看到补丁来完成这项工作,并启用可睡眠跟踪点程序的附加功能。 这很可能会导致Linux跟踪基础架构能力的进一步提高。
本文索引条目 | |
---|---|
内核 | BPF/跟踪 |
内核 | 跟踪/使用 BPF |
(登录后发表评论)