中速ARMv7プロセッサで実行される2.6.35 PREEMPTカーネルがあります。約100〜125秒ごとにカーネルがアンダーランを防ぐのに十分な速さで特定のオーディオ関連ドライバを処理できないという問題が発生します。保持時間は通常15〜30msの範囲ですが、長くなることもあります。この遅延が完全にカーネルで発生するのか、それともリアルタイム優先順位(SCHED_RR、2)で実行されるユーザープロセスのスケジューリングと関連があるのかは不明です。
私の推測では、プリエンプション能力が低下するドライバが1つ(少なくとも1つ)あるということです。
ユーザー・プロセスの一部の strace 出力は、正常な動作と異常な動作のいくつかの側面を示しています。さまざまな時間レポートを解釈する方法がわかりません。
正常な状況:
0.000518 poll([{fd=10, events=POLLIN|POLLERR|POLLNVAL, revents=POLLIN}], 1, 3415) = 1 0.010202 poll([{fd=10, event=POLLIN|POLLERR|POLLNVAL}, {fd=6, event=POLLOUT|POLLERR|POLLNVAL, revents=POLLOUT}], 2, 3404) = 1 0.000585 poll([{fd=10, event=POLLIN|POLLERR|POLLNVAL}, {fd=6, event=POLLOUT|POLLERR|POLLNVAL, revents=POLLOUT}], 2, 3404) = 1 0.000302 poll([{fd=10, events=POLLIN|POLLERR|POLLNVAL, revents=POLLIN}], 1, 3404) = 1 0.010706 poll([{fd=10, events=POLLIN|POLLERR|POLLNVAL}, {fd=6, events=POLLOUT|POLLERR|POLLNVAL, revents=POLLOUT}], 2, 3393) = 1 0.000480 poll([{fd=10, events=POLLIN|POLLERR|POLLNVAL}, {fd=6, events=POLLOUT|POLLERR|POLLNVAL, revents=POLLOUT}], 2, 3392) = 1
fd6の出力をポーリングするとブロッキングは発生しませんが、fd10の入力のみをポーリングすると約10ms程度のブロッキングが発生します。これは、システムコール期間のレポートとシステムコールの間の時間(一貫性)の両方に反映されます。
失敗事例(極端な例):
0.000305 poll([{fd=10, events=POLLIN|POLLERR|POLLNVAL, revents=POLLIN}], 1, 3543) = 1 0.010730 poll([{fd=10, event=POLLIN|POLLERR|POLLNVAL}, {fd=6, event=POLLOUT|POLLERR|POLLNVAL, revents=POLLOUT}], 2, 3533) = 1 0.000475 poll([{fd=10, event=POLLIN|POLLERR|POLLNVAL}, {fd=6, event=POLLOUT|POLLERR|POLLNVAL, revents=POLLOUT}], 2, 3532) = 1 0.000329 poll([{fd=10, events=POLLIN|POLLERR|POLLNVAL, revents=POLLIN}], 1, 3532) = 1 0.953349 poll([{fd=10, event=POLLIN|POLLERR|POLLNVAL}, {fd=6, event=POLLOUT|POLLERR|POLLNVAL, revents=POLLOUT|POLLERR}], 2, 2578) = 1
この例では、2回目の呼び出しが10ミリ秒(通常)かかると記録されていますが、最後の呼び出しでまだ953ミリ秒が残ります。
犯人を追跡するにはどのツールを使用できますか?
ベストアンサー1
perf
あなたに役立つかもしれません。これはLinuxカーネルユーティリティの一部です。
たとえば、
perf record -R -a -g fp -e cycles -e syscalls:sys_enter_poll -e syscalls:sys_exit_poll
#Just ctrl+c if you are done, and view ith
perf script
すべてのシステムコールの開始/終了時間とパラメータ(straceなど)を表示し、システムコールを呼び出したバイナリの名前を指定し、一定の頻度(カーネル記号を含む)で各CPUの呼び出しスタックをサンプリングします。これにより、実際にシステムコール中にどのコードが実行されているかを確認できます。マルチプロセッサシステムでは、CPU ID(例:[001])に注意する必要があります。