3

これはLinux上にありますが、理想的にはPOSIX準拠のソリューションが必要です。

API関数を介してハードウェアバスに書き込むことができる2つのスレッドがあります。常に1つのスレッドのみがバスに書き込むことが許可されており、バスの書き込み後、数百ミリ秒のオーダーの特定の時間にバスに書き込むことはできません。

両方のスレッドはステートマシンとして実装されます。

明らかな解決策は、ミューテックスを使用してバスへのアクセスをシリアル化し、カウンターまたはタイムスタンプを設定し、適切な時間が経過した後にステートマシンにミューテックスのロックを解除させることです。

これは私には少し壊れやすいようです。将来のメンテナンス開発者がステートマシンを誤って変更すると、ミューテックスが解放されず、デッドロックの診断が困難になる可能性があります。

ミューテックスをロックするが、指定されたタイムアウト後に自動的にロックを解除するAPI呼び出しはありますか?Googleはpthread_mutex_timedlock()を明らかにしていますが、これはまったく同じことではありません。

4

3 に答える 3

3

ロックを自動的に解放できるpthreadsAPIを知りません。

個人的には、これらの複雑さを回避するために、単一のスレッドを介してバスへのアクセスをシリアル化しようとします。そのスレッドが入力キューを維持し、他のスレッドがそのスレッドに要求を送信する場合、必要なシリアル化と競合解決を実行できます。これにより、さらにアクセスする前の遅延の実装も容易になります。このスレッドでブロッキング関数を使用しないように注意している限り、実際の失敗の唯一のケースは、誤って終了する可能性があることです。

バスからの読み取りと書き込みの両方が必要な場合は、すべてのスレッドに入力キューを与え、ワーカースレッドに「読み取り要求」をIOスレッドに送信させてから、応答が独自の入力キューにポストバックされるのを待つことができます。スレッドに対する未処理のリクエストが1つしかない場合は、キューは実際には必要ありません。単純な条件変数と、入力する構造体へのポインターが適切に機能する可能性があります。

2つのスレッドでリソースを共有したい場合は、ミューテックスがロックされるリスクが常にあると思います。タイマーを設定し、一定時間後にミューテックスを強制的に解放したとしても、実際には別のスレッドによって完全に保持されているにもかかわらず、スレッドがロックを持っていると信じてリソースを使用し続けるという別のバグが発生する可能性があります。最終的には、将来のプログラミングエラーに対する堅牢性を計画しようとしています。これはすばらしい目標ですが、制限があります。ミューテックスは注意が必要なものです。

ミューテックスルートを使用する必要がある場合の最善のアプローチは、ミューテックスを必要とするコードを単純に最小化し、その中の呼び出しをブロックしないようにすることです。ステートマシンを実装している場合は、状態遷移の間にミューテックスがロックされたままになる必要がないことを確認してください。可能であれば、ミューテックスロックのスコープを設定して、コールチェーンのあるレベルで単一の関数呼び出しの間だけ保持されるようにします。これにより、ロック/ロック解除の不一致を目で見つけるのがはるかに簡単になります。C ++を使用している場合は、RAIIを使用して、ロックの解放の信頼性を高めます。

しかし、繰り返しになりますが、通常は1つのスレッドをアービター(既存のスレッドまたは新しいスレッドのいずれか)として宣言することで、何らかの方法でリクエストをシリアル化する方がはるかに簡単だと思います。

于 2013-01-18T11:54:44.663 に答える
1

How about having a timestamp of last bus access in shared (and mutex-covered) memory? Each write would than look like this:

  1. lock mutex
  2. check timestamp of last access; if your wait-time has not passed yet, sleep for remainder of this time, as you cannot do anything else in this thread anyway
  3. do the write
  4. update timestamp of last access
  5. unlock mutex
于 2013-01-18T11:59:39.463 に答える
1

この問題に直面した場合は、おそらく別の「APIwrite」スレッドを使用してドライバーと対話します。このスレッドは、生産者/消費者キューポップとスリープ(数百ミリ秒)をループします。書き込みを希望する他のスレッドは、*writeBufferをキューに入れるだけです。writeBuffer構造体には、APIwriteスレッドが書き込み後に呼び出すfunction(* writeBuffer)ポインターを含めることができます。発信元スレッドによって提供されるこの関数は
、発信元スレッドが待機しているイベントを通知するか、*writeBufferを解放することができます。

明示的なミューテックス、タイマーなどをいじくり回すのを防ぎ、同期または非同期書き込みを可能にします。

于 2013-01-18T12:12:28.683 に答える