web-dev-qa-db-ja.com

ライブラリ関数への呼び出しのシステム全体の監視

多くのプロセスが同時に実行されている最新のLinuxデスクトップがあります。それらのプロセスの1つで、どれがどれかはわかりませんが、人気のあるダイナミックライブラリsome_funcから関数some_libを呼び出します(libcまたはlibx11を考えてください。したがって、- lotのプロセスがそれを使用します)、そしてどのプロセスがそれを行うのか知りたいです(そして理想的には、各呼び出しのスタックトレースがあります)。

どのプロセスがsome_libを呼び出すかを判断するにはどうすればよいですか?

これまでに検討したオプション:

  1. ltraceまたはlatraceを使用します。どの引数が完璧であるかについて、興味のある関数を呼び出すプロセスのltraceスタイルの詳細なリストを用意しますが、ltraceは個々のプロセスまたはプロセスグループでのみ機能します。 ltrace -e some_func@some_lib -fp 1と入力して、システム全体のすべての使用法を確認することはできません。
  2. lsofでライブラリを使用しているプロセスを見つけて、手順1に進みます。同じライブラリを使用しているが、その関数を呼び出さないプロセスが多すぎるため、これは非常に面倒です。
  3. grep -r some_func /usr次に、関数を呼び出すことができるバイナリが2つしかないかどうかを確認し、そこから作業を進めます。 couldいくつかの限られたケースで機能しますが、これは決して一般的な解決策ではなく、たとえば次の場合は機能しません。 some_funcはさまざまなバイナリに遍在していますが、呼び出されることはめったにありません。
  4. カーネル監査システムを使用します。システムコールをトレースしている場合は、auditctl -S some_syscall ...と入力すると、システム全体の呼び出しをログに記録するのに役立ちます。ただし、auditctlは、ライブラリ関数と同じレベルの粒度を実行できないようです。
  5. 最後に、rebuildライブラリを使用して、関心のある関数にすべての呼び出しをログに記録する新しい行を追加することができます。これは私の問題を解決することが保証されますが、その解決策は面倒であり、ライブラリを変更/再コンパイルし、インストルメントされたライブラリをロールアウトして原因を見つけた後にロールバックするために少なくとも2回再起動する必要があります。

もっと簡単な方法はありますか?

(これは一般的な質問であり、ほとんどの場合、正しく機能する一般的なソリューションに関心があることを指摘したいと思います。)


ニースを見つけました 比較記事 私が知らなかったいくつかのトレース機能について言及しているので、調べる価値があるかもしれません。

Debuginfoを使用したSystemTapは、ライブラリ内の関数呼び出しをトレースできます。 Centos 7システムの場合:

$ Sudo stap -L 'process("/lib64/libglib*").function("*strndup*")'
process("/usr/lib64/libglib-2.0.so.0.5000.3").function("g_strndup")
$ 

そして、これは、バックトレースまたはSystemTapで記述できる必要なものを出力するprobeポイントとして使用できます。

probe begin {
    printf("ok\n")
}
probe process("/usr/lib64/libglib-2.0.so.0.5000.3").function("g_strndup") {
    /* printf("%s[%d]\n", execname(), pid()) */
    print_usyms(ubacktrace())
}

probelibraryfunc.stpとして保存これは経由で実行できます

$ Sudo stap probelibraryfunc.stp

ただし、呼び出しが一般的である場合は、異常な量の出力が生成される可能性があります...

4
thrig