【问题标题】:how to avoid printk log dropping in linux kernel如何避免 Linux 内核中的 printk 日志丢失
【发布时间】:2014-12-12 08:55:33
【问题描述】:

有没有什么技巧或方法可以避免内核日志丢失或日志缓冲区溢出?

我已通过以下代码更改将日志缓冲区大小增加到最大值。我只在高端设备上运行。但是,当我想从我的驱动程序(写入大量日志)获取完整日志时,我看到 printk 日志有时会被丢弃。我使用带有 KERN_INFO 的 printk,通过动态调试(dprintk)启用。

改变我做的:

--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -55,7 +55,7 @@ void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...)
 {
 }

-#define __LOG_BUF_LEN  (1 << CONFIG_LOG_BUF_SHIFT)
+#define __LOG_BUF_LEN  (1 << 17)

我用来写入文件的命令:

cat "/proc/kmsg">/sdcard/klog.txt

仅在调试时,如果我的驱动程序性能下降,我可以,但我不想丢弃任何日志。我知道我们不能让工作队列/线程等到打印完成。但是,仍然有任何方法可以保证日志不会被丢弃。

【问题讨论】:

  • # tail -f /var/log/messages &gt; /tmp/tmplog.txt &amp; 是解决此问题的一种简单方法。

标签: logging linux-kernel linux-device-driver embedded-linux printk


【解决方案1】:

两种方式:

  1. cat /proc/kmsg &gt; some file location &amp;

  2. 这更详细: 由于日志记录过多,根本不要使用dmesg 缓冲区?

A> 在驱动程序初始化期间,为所需大小的日志记录分配单独的缓冲区空间(大缓冲区)

B> 创建一个单独的函数来记录它,比如my_log_buf("Debug check point 1");,它会登录到上述缓冲区

C> 给出一个读取系统接口,使用 cat /sys/(一些暴露的接口) 读取它

【讨论】:

    【解决方案2】:

    很简单,只需将“printk.synchronous=1”添加到内核命令行即可。

    printk() 现在已经完全异步了。您可以添加 printk.synchronous=1 让 printk() 同步。

    参考补丁“printk:使 printk() 完全异步”:

    目前,printk() 有时会等待消息被打印到 控制台,有时它不会(当 console_sem 被某些人持有时 其他过程)。如果 printk() 抓取 console_sem 并开始打印 到控制台,它从内核 printk 缓冲区打印消息,直到 缓冲区为空。连接串行控制台时,打印速度慢且 因此系统中的其他 CPU 有足够的时间来追加新的 一个 CPU 正在打印时向缓冲区发送消息。这样CPU就可以 在 console_unlock() 中花费无限时间进行打印。 如果 printk() 调用,这是一个特别严重的问题 在禁用中断的情况下调用了 console_unlock()。

    在实践中,用户观察到 CPU 可能会花费数十秒 在 console_unlock() 中打印(通常在启动过程中,当数百 SCSI 设备被发现)导致 RCU 停顿(CPU 执行 打印长时间未达到静止状态),软锁定 报告(打印 CPU 的 IPI 没有得到服务,因此其他 CPU 正在旋转,等待打印 CPU 处理 IPI),并且 最终机器死亡(因为来自停顿和锁定的消息附加 以比我们能够打印的速度更快地打印缓冲区)。所以这些机器 无法在连接了串行控制台的情况下启动。另一个观察到 问题是由于 printk 速度慢,硬件发现速度慢,而 udev 在内核设法发现所有附加的硬件之前超时。还 在人工压力测试期间 SATA 磁盘从系统中消失 因为它的中断服务时间不会太长。

    这个补丁使 printk() 完全异步(类似于 printk_deferred() 一直到现在为止)。它将消息附加到内核 printk 缓冲区和 wake_up()s 是一个特殊的专用 kthread 来执行 打印到控制台。这样做的好处是总是打印 发生在可调度的上下文中,因此我们不会锁定任何 特定的 CPU 甚至中断。它还有一个优点是 printk() 速度很快,因此内核启动不会因为慢而减慢 串行控制台。这种方法的缺点是在崩溃的情况下 重要消息不会出现在控制台中的可能性更高 输出(我们可能需要工作调度以将消息打印到控制台)。 我们通过将 printk 切换到原始版本在一定程度上减轻了这种风险 如果 oops 正在进行,则立即打印到控制台的方法。

    异步 ​​printk 暂时被认为不太可靠 比同步的,所以默认情况下我们保持 printk 运行 同步模式。有一个 printk.synchronous 内核参数 允许选择同步/异步模式作为启动参数或稍后从 用户空间通过 sysfs 旋钮。

    printk() 预计可以在不同的条件下工作 不同的场景,包括 OOM 的极端情况,当所有 工人很忙(例如分配内存),因此 printk() 使用它自己的 专用打印kthread,而不是依赖workqueue(甚至 设置 WQ_MEM_RECLAIM 位后,我们可能会收到延迟 打印直到 workqueue 声明 ->mayday,如 Tetsuo 所述 汉达)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-06
      • 2021-08-27
      • 2018-01-20
      • 1970-01-01
      相关资源
      最近更新 更多