2016-03-31 7 views
2

を返します。のprintfが、私はそうのように、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

printf/IOLogは、ユーザスペースにメッセージを送信するためにバッファを使用し、そこでシステムログに記録されます。たくさんのメッセージを出力すると、このバッファはログデーモンがそれをクリアする前に一杯になることがあり、メッセージは切り捨てられ、互いに実行されます。 (printf/IOLogは、メッセージがバッファに提出されるとすぐに返され、デーモンがそれを受け取るのを待つことはありません)。

また、カーネルprintf/IOLogが何らかの方法であればスレッドセーフなので、複数のスレッドから同時に呼び出すと競合状態が発生することもあります。私は、ソースを確認して確認する必要があります。

kprintfは完全に同期しており、メッセージがシリアルポートで送信されるか、FireWire経由で送信されるまでブロックされます。スレッドセーフでもあります。ファイヤワイヤの場合、kprintfの出力もバッファされるので、lotのメッセージを出力すると、これもいっぱいになり、切り捨てが発生します。 fwkpfvコマンドを使用すると、--buffer引数を使用してバッファサイズを指定することができます。そのため、それを打ち消すことができます。同期しているkprintfの欠点は、大量のメッセージでシステムをかなり遅くすることができることです。

+0

ありがとうございました。これは調査目的に過ぎないため、パフォーマンスは問題ではありません。だから私は 'kprintf'を使う必要があります。 2台のマシン/ VMを使用せずに 'kprintf'出力を何とか取得できますか?理想的には、kprintf出力をログファイルに書きたいと思います... – Joseph

+0

私が知っている限り、kprintfはシリアルポート(主にVMの場合は最近のところ便利です)やFireWireでしか使用できません。 printfを使用する代わりに、IOSharedDataQueueまたはカーネル制御ソケットを使用して、カスタムユーザー空間ロギングシステムを構築できます。 – pmdj

関連する問題