系统调用中的printf返回格式错误的输出

时间:2016-03-31 08:07:25

标签: linux macos kernel system-calls xnu

我使用kext在OS X中记录系统调用,如下所示:

int hook_read(struct proc *p, struct read_args *u, user_ssize_t *r) {
    /* get som params here... */
    printf("[IDEN] SYS_read called, %s, %d, %d, %d.\n", params);
    return read(p, u, r); 
}

这会记录到system.log。现在的问题是,如果printf负载很高(调用了许多系统调用),system.log中的输出通常会格式错误: 例如ID]SYS_readEN] callparam, 123, ed 123, 123。字符串被扰乱了。如果我使用kprintf打印到串行端口,则不会出现格式错误的日志。

非常感谢任何有关导致此行为的想法!

1 个答案:

答案 0 :(得分:1)

printf / IOLog使用缓冲区向用户空间发送消息,然后将其记录到系统日志中。如果输出大量消息,则在日志记录守护程序有机会清除它之前,此缓冲区可能已满,并且您的消息将被截断并开始相互运行。 (一旦消息被提交到缓冲区,printf / IOLog就会返回,并且不会等待守护进程接收它。)

此外,我不确定内核printf / IOLog是否在线程安全,因此也可能是从多个线程同时调用它会导致竞争条件。我必须检查来源以确定。

kprintf是完全同步的,并且将阻止,直到您的消息在串行端口上传输或通过firewire提交。它也是线程安全的。在firewire的情况下,kprintf输出也是缓冲的,所以如果你输出很多的消息,这也会填满并导致截断。 fwkpfv命令允许您使用--buffer参数指定缓冲区大小,因此您可以抵消它。 kprintf同步的缺点是它可以通过大量消息大大减慢系统速度。