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

问题描述 投票:0回答:1

我正在使用 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
(它打印到串行端口),则永远不会出现格式错误的日志。

非常感谢任何导致这种行为的想法!

linux macos kernel system-calls xnu
1个回答
2
投票

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

此外,我不确定内核

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

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

© www.soinside.com 2019 - 2024. All rights reserved.