3

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

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

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

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

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

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

4

1 回答 1

2

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

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

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

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

于 2012-10-03T20:28:55.060 回答