我在内核可加载模块中使用printk来记录系统调用的参数。对于每个系统调用,使用几个printks来打印它们以“\ t”作为分隔符出现的变量。要将内核日志缓冲区中的数据重定向到除system / var / log / messages之外的另一个文件,我使用“klogd -f”来绕过syslog接口。获得的日志数据是每个系统调用一行。但是,在分析数据后,我发现存在2个问题。
问题1:数据可能会丢失。
问题2:一个系统调用的数据与属于另一个系统调用的数据混合,可能在中间。
问题1:内核日志缓冲区溢出导致的数据丢失是否会覆盖缓冲区中最旧的日志?如果是这样,如何克服它?我计划增加内核日志缓冲区的大小。你认为这是合适的,最适合的尺寸是什么?
问题2:系统呼叫可以抢占另一个系统呼叫吗?或者在某些情况下,一个系统调用可能会调用另一个系统调用,并且除非被调用的系统调用完成,否则无法完成?这是数据相互混合的原因吗?
问题3:printk原子?如果没有,如何使printk原子?添加锁以使其不可中断?
答案 0 :(得分:2)
如果您只想转储程序正在进行的所有系统调用(带参数),check out strace
命令。
问题1:排序。内核日志缓冲区实现为环形缓冲区。如果环形缓冲区为128K,并且内核在引导后总共写入了129K的数据,则第一个1K将被最新数据覆盖。您可以通过内核引导参数log_buf_len
或在内核的.config文件中的编译时增加此缓冲区的大小。您还可以使用dmesg更改环形缓冲区的大小,方法是运行dmesg -s524288
将其设置为512KiB。您必须根据要吐出的数据量确定最佳尺寸。
问题2:一个系统调用可能会抢占另一个系统调用,并且内核中还有许多其他抢占案例 - 中断服务例程就是一个很好的例子。此外,如果您使用的是多核系统,则可以拥有多个活动内核线程。
问题3:我相信printk试图锁定内核的环形缓冲区。这有点复杂,因为你可以从恐慌状态调用printk。