5

是否有任何提示或方法可以避免内核日志丢失或日志缓冲区溢出?

通过以下代码更改,我已将日志缓冲区大小增加到最大值。我只在高端设备上运行。但是,当我想从我的驱动程序(写入大量日志)获取完整日志时,我看到 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

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

4

2 回答 2

3

很简单,只需将“ 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 缓冲区打印)。因此,这些机器无法在连接了串行控制台的情况下启动。另一个观察到的问题是,由于 printk 速度慢,硬件发现速度很慢,并且 udev 在内核设法发现所有附加的硬件之前超时。

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

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

printk() 预计在不同的条件和不同的场景下工作,包括当所有工作人员都忙(例如分配内存)时 OOM 的极端情况,因此 printk() 使用自己的专用打印 kthread,而不是依赖于工作队列(即使设置了 WQ_MEM_RECLAIM 位,我们也可能会收到打印延迟,直到工作队列声明 ->mayday,如 Tetsuo Handa 所述)。

于 2017-04-01T04:20:37.490 回答
1

两种方式:

  1. cat /proc/kmsg > some file location &

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

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

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

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

于 2014-10-26T17:36:27.717 回答