【问题标题】:printf in system call returns malformed output系统调用中的 printf 返回格式错误的输出
【发布时间】:2016-07-19 13:33:13
【问题描述】:

我正在使用 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】:

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

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

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

    【讨论】:

    • 谢谢。性能不是问题,因为这仅用于调查目的。所以我必须使用kprintf。我可以在不使用两台机器/VM 的情况下以某种方式获取kprintf 输出吗?理想情况下,我想将 kprintf 输出写入日志文件...
    • 据我所知,您只能将 kprintf 与串行端口(目前主要在 VM 中使用)或火线一起使用。您始终可以使用 IOSharedDataQueue 或内核控制套接字来构建自定义用户空间日志系统,而不是使用 printf。
    猜你喜欢
    • 1970-01-01
    • 2010-11-06
    • 2020-04-14
    • 2012-02-21
    • 1970-01-01
    • 2020-02-27
    • 1970-01-01
    • 1970-01-01
    • 2014-06-17
    相关资源
    最近更新 更多