4

Linux 2.6.32.20 を実行する ARM9 ベースの組み込みボードがあります。このデバイスは、関連するキャプチャ/圧縮ハードウェアがデータを ARM メモリ内の入力 fifo に配置するビデオ カメラであり、ARM はユーザー空間からアクセスします。高レベルの制御用に、このエンコーダー用のドライバーも用意しています。

アプリケーション レベルのコード内のスレッドは、このユーザー空間の fifo をチェックし、データがある場合は、これをソケット経由で送信します。データのユーザー空間 fifo をポーリングする必要があるこのスレッドのオーバーヘッドを回避するために、ドライバーへの非常に単純な read() 呼び出しがあります。 read() 呼び出しで提供されるバッファ)。その後、この read() 呼び出しが返され、スレッドは fifo からデータが空になるまで読み取りを続行し、その後、偽の read() 呼び出しを呼び出して再び待機します。

このシステムは、フレーム ドロップが検出される前に送信できるネットワーク ストリームの数によって測定されるように、非常に効率的です。しかし、偽の read() 呼び出しを使用すると、Linux の「top」ユーティリティがアプリによる大量の CPU 使用率を報告することが判明しました。

2 つのバージョンのアプリを作成しました。1 つは上記のように動作し、もう 1 つは偽の read() を呼び出さずに代わりに usleep() 呼び出しを介在させて fifo をポーリングすることを除いて同一です。それぞれが 5 つのストリームを送信している 2 つのケースについて、「top」によって報告された CPU 使用率を見ると、次のようになります。

1) read() バージョン: CPU 12%
2) usleep() バージョン: CPU 4%

もちろん、実際のポーリングは効率が悪く、「トップ」が言っていることを無視して、フレーム ドロップが発生する前に 2 つのバージョンが同時に送信できるネットワーク ストリームの数を測定すると、上記のバージョン 1 が優先されます。

上記の read() 呼び出しが正しく動作することを確認しました。fifo にデータがなくても read() 呼び出しがすぐに返されるというバグが発生した場合、スレッドは高価な連続ポーリングを実行することになります。しかし、そうではありません。read() 呼び出しにより、スレッドは 1 秒あたり正確に 30 回実行されます。

私たちは、おもちゃのビジーボックス バージョンの "top" によって取られた近道があるのではないかと考えました。

この問題は、Linux カーネル自体が /proc//stat に示されている数値を収集する方法に何らかの制限があるに違いありません。

なぜこれが必要なのかを誰かが理解している場合は、私を正しい方向に向けてください。ありがとう!

4

2 に答える 2

1

トップがあなたに嘘をついていないことを保証できます。プロセスが CPU の 12% を使用していると表示されている場合は、CPU の 12% を使用しています。それについて2つの方法はありません。

明らかに、usleep の呼び出しにそれほど時間はかかりません。プロセスが (少なくとも) 要求された時間だけスリープ状態になるためです。これはおそらく、スリープの呼び出しごとに 100 サイクルです。Read はそれよりもはるかに多くのことを行うので、それを行うのに CPU 時間がかかることは驚くことではありません。特に、頻繁に行う場合はなおさらです。

読んでください:

  1. ハンドルが有効であることを確認してください。
  2. バッファー ポインターと長さが有効であることを確認します。
  3. 長さをユーザー空間からカーネル空間にコピーします。
  4. 読み取ったデータを適切なデータ構造に挿入します。
  5. 関連するハンドルと、要求を発行するドライバーを検索します。
  6. ドライバーに読み取り要求を発行します。
  7. ドライバーはプロセスをスリープします [利用可能なデータがないことを前提としています]。
  8. ドライバーは [利用可能なデータがある場合] プロセスを起動します。
  9. 読み取った長さデータをユーザー空間にコピーします。
  10. 呼び出し元に戻ります。

それをusleepと比較してください:

  1. 寝る。
  2. 起きろ。
  3. ユーザーに戻ります。

コルセの「眠りにつく」ことは、ただの些細な機能ではないし、目覚めることも些細なことではない。ただし、これらは同じ操作であり、スリープ中はプロセスは CPU を使用しません。

/dev/zero から読み取り、その間にスリープすることで、読み取りにどれだけのオーバーヘッドがあるかを簡単に把握できます。/dev/zeroゼロで満たされたバッファですぐに戻るデバイスです。

oprofileまたは、パフォーマンス分析などを使用して、時間が費やされている場所を確認することもできます。

しかし、私はあなたtopが嘘をついていないことを確信しています。

于 2013-01-10T21:26:38.767 に答える