【问题标题】:printk data loss and truncationprintk 数据丢失和截断
【发布时间】:2012-10-03 20:14:31
【问题描述】:

我在我的内核可加载模块中使用 printk 来记录系统调用的参数。对于每个系统调用,使用几个 printk 来打印变量,它们以“\t”作为分隔符出现。要将内核日志缓冲区中的数据重定向到系统 /var/log/messages 以外的另一个文件,我使用“klogd -f”绕过 syslog 接口。每次系统调用获取的日志数据为一行。但是,在分析数据后,我发现存在两个问题。

问题一:数据可能会丢失。

问题 2:一个系统调用的数据与属于另一个系统调用的数据混合在一起,可能在中间。

问题1:是内核日志缓冲区溢出覆盖了缓冲区中最旧的日志造成的数据丢失吗?如果是这样,如何克服它?我计划增加内核日志缓冲区的大小。你觉得合适吗?什么尺寸最好?

问题2:系统调用可以抢占另一个系统调用吗?或者在某些情况下,一个系统调用可能会调用另一个系统调用并且除非被调用的系统调用完成,否则无法完成?这就是数据混在一起的原因吗?

问题 3:printk 是原子的吗?如果没有,如何使 printk 原子化?添加锁以使其不可中断?

【问题讨论】:

    标签: system-calls buffer-overflow data-loss printk


    【解决方案1】:

    如果您只想转储程序正在进行的所有系统调用(带参数),check outstrace 命令。

    问题1:有点。内核日志缓冲区被实现为一个环形缓冲区。如果环形缓冲区为 128K,并且内核自启动后总共写入了 129K 的数据,则前 1K 将被最新数据覆盖。您可以通过内核引导参数log_buf_len 或在编译时在内核的.config 文件中增加此缓冲区的大小。您还可以使用 dmesg 更改环形缓冲区的大小,通过运行 dmesg -s524288 将其设置为 512KiB。您必须根据输出的数据量确定最佳大小。

    问题 2:一个系统调用可能会抢占另一个系统调用,并且内核中还有很多其他抢占的情况——中断服务例程就是一个很好的例子。此外,如果您使用的是多核系统,则可能有多个活动内核线程。

    问题 3:我相信 printk 试图锁定内核的环形缓冲区。不过这有点复杂,因为您可以在恐慌状态下调用 printk。

    【讨论】:

    • 试着在你的模块中保存你自己的调试缓冲区并编写一个系统调用来转储它,也许吧?我不清楚你的总体目标。如果您只是记录系统调用,请查看strace 命令。
    • 嗨,本。感谢您对 strace 命令的建议。但是strace需要事先知道具体的程序日志,而我需要的是全系统的系统调用日志。也就是说,我的总体目标是拦截曾经在系统上运行过的所有进程的所有系统调用的参数。因此,日志数据将是“大数据”,需要较大的缓冲区空间,并及时转储缓冲区内容。
    • Eesh。是的,这是一个复杂的问题。您可以虚拟化您的环境吗?如果是这样,您也许可以利用 qemu 中的调试环境来获取此数据。例如,编写一个连接到 qemu 调试服务器的程序,在您关心的系统调用中抛出断点,并在执行停止时记录任何必要的数据。如果您使用的机器允许,您也可以使用 JTAG 仿真器执行此操作。 cs.rochester.edu/users/faculty/sandhya/csc256/assignments/…
    • 无论哪种方式,如果您确实提出了解决方案,请考虑将其发布在 GitHub 上并让内核开发人员知道它。他们喜欢这样狡猾的调试工具。
    • 还要考虑,如果您在记录数据的同一台机器上使用任何类型的用户空间组件执行此操作,它肯定会导致额外的系统调用。事实上,用户空间组件可能无法做到这一点,除非它足够聪明,可以排除自己的调用——因为最终它只会用自己的数据递归地阻塞自己。
    猜你喜欢
    • 2017-09-22
    • 2010-10-04
    • 1970-01-01
    • 1970-01-01
    • 2014-11-10
    • 2013-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多