10

さて、この質問はスレッド管理に関するものではありません...そうですね。この構成に対するさまざまなソリューションを探しています。いくつかのアイデアがありますが、問題を解決できる解決策を探しています。そして、長所と短所を比較検討して、最適なものを実装します。

これが状況です。

スレッドを生成するマネージャー アプリケーションがあります。このスレッドは継続的に実行され、USB 経由でシステムに接続されたボードとのシリアル通信を処理します。マネージャー アプリケーションは、システム上で実行されている他のアプリケーションとこのスレッドとの間の通信を容易にします。スレッドは、次の 2 つのことを実際に実行する必要があります。

  1. 可変タイマーでシリアル経由でボードにサンプル データをポーリングします。通常は 1 分に 1 回程度です (シリアル バスはかなり遅く、ボーは 4800 です。これを制御することはできません)。
  2. マネージャー アプリケーションとの通信を容易にします。(つまり、他のアプリケーションがサンプル データを要求すると、マネージャはその要求をスレッドに転送します。スレッドは操作を実行し、データを返します)

私の最初のデザインはシンプルなもので、うまくいきました。マネージャーからスレッドへの通信にキューとミューテックスを使用します。したがって、スレッドのロジックは次のとおりです。

  1. 初期化
  2. 管理者からシャットダウンコマンドを受け取っていない間
  3. タイマーが切れたら、ボードをポーリングしてデータを取得します
  4. それ以外の場合は、マネージャーによってキューに投稿されたメッセージがあるかどうかを確認してください。あれば処理する

問題は、CPU 使用率を考慮していないことです。99.9% の時間、私のスレッドは何も処理しておらず、電力を消費しています。やるべきことがあるまで、このスレッドをスリープ状態にする方法を実装する必要があります。だからいくつかのアイデア:

select() を使用してブロックします。これは、使用する必要があるタイマーに基づいてブロックでき、キュー メッセージングの実装をソケット メッセージングに変更できます。代わりに、スレッドはマネージャに対してクライアント ソケットを開き、マネージャはソケットを介してメッセージをスレッドに渡します。次に、select() は、fd でアクティビティが発生するか、タイマーが作動するまでスリープします。

長所: まさに必要な機能です。

短所: ソケットは、既にメモリを共有しているスレッドと通信するための処理が少し重くありませんか?

信号システムを使用してください。(Linux の知識が豊富な人なら、ここで実装例を示してくれるかもしれません。正確な方法はわかりません。) しかし、スレッドはタイマーの間スリープし、シグナルが発生した場合に処理するためにウェイクアップすることができます。マネージャーから受け取った。

メリット: 共有メモリを使用して現在の実装を維持

短所:実装方法がわからない。fds の代わりにシグナルで動作する select() のような関数はありますか?

ミューテックスの可能性があります。マネージャーがミューテックスに投稿するまでブロックできました。

長所: 引き続きメモリを共有する

短所:タイマー処理をマネージャーに移動する必要があるかもしれませんが、他のタイマーと実行する重要な作業があるため、実際にはオプションではありません。

お勧めし、気軽に批評してください。私は効率的なオプションを受け入れます。ただし、これは組み込みシステムで実行されているため、リソースの使用が重要であることに注意してください。

4

5 に答える 5

5

このような状況を処理するための従来のツールはセマフォであり、ミューテックスや条件変数ではありません。マネージャーからスレッドに渡されるトークンと考えてください。

スレッドはsem_timedwait、データをチェックするために時々確実にウェイクアップするために使用できます。

関数のエラーリターンをsem_うまくキャプチャするように注意してください。それらは割り込み可能です。そのため、あなたが思っているよりも少し多くの目覚めがあるかもしれません.

于 2012-06-29T14:44:31.800 に答える
4

セマフォを使用して、次のようなことを試してください。

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

static sem_t s_sem;
static int iAlive = 1;

void* thFunc(void *param)
{
    printf("%s : ENTER \n", __FUNCTION__);
    while(iAlive)
    {
        printf("%s : waiting \n", __FUNCTION__);
        sem_wait(&s_sem);

        printf("%s : got a signal - doing something \n", __FUNCTION__);
        sleep(1);
    }

    printf("%s : EXIT \n", __FUNCTION__);
    return 0;
}

int main()
{
    pthread_t thread;
    sem_init(&s_sem, 0, 0);

    if(0 != pthread_create(&thread, NULL, thFunc, NULL))
    {
        printf("%s : pthread_create FAILED \n", __FUNCTION__);
        return -1;
    }

    while ( getchar() != 'q' )
    {
        printf("%s : sending signal \n", __FUNCTION__);
        sem_post(&s_sem);
    }

    iAlive = 0;
    sem_post(&s_sem);
    pthread_join(thread, NULL);
    sem_destroy(&s_sem);

    return 0;
}

sem_waitタイムアウトが必要なsem_timedwait場合は、に置き換えることができます。

于 2012-07-02T08:04:15.273 に答える
4

独自のメッセージ キューではなく、POSIX メッセージ キューに切り替えます。 mq_timedreceiveマネージャーがリクエストを投稿すると返されます。タイムアウトした場合は、タイマー ポーリングを実行する必要があります。同期とブロックはすでにパッケージ化されています。

于 2012-06-29T14:43:23.063 に答える
3

各スレッドは、タイムアウト付きの入力プロデューサー/コンシューマー キューで待機します。キューの待機がタイムアウトした場合は、シリアル リンクをポーリングします。それ以外の場合は、キューで受信したコマンドを処理します。適切なキューを最初から作成するには、実際のキュー (既に持っている)、キュー ポインター/インデックスを保護するミューテックス (既に持っている)、および 0 に初期化され、wait(タイムアウト) 関数。スレッドにリクエストを送信するには、ミューテックスをロックし、リクエストをプッシュし、ミューテックスをロック解除し、セマフォにシグナルを送ります。スレッドで、セマフォを待機し、タイムアウトなしで待機が返された場合は、ミューテックスをロックし、リクエストをポップし (常に存在するため)、ミューテックスをロック解除し、受信したリクエストを処理します。sema 待機がタイムアウトで戻る場合は、シリアル リンクをポーリングします。完了したら、ループしてセマフォを再び待ちます。

タイムアウトを変更するには、コマンド 'EchangeWaitInterval' (たとえば:) を含むメッセージと、後続の待機に使用する新しいタイムアウト間隔をスレッドに送信します。

于 2012-06-29T14:41:13.037 に答える
0

これに対する従来の pthreads のアプローチはpthread_cond_wait()、マネージャー スレッドがメッセージをキューに入れ、条件変数を通知するまで、スレッドをブロックすることです。この場合、タイムリーにウェイクアップしてシリアル デバイスをポーリングするには、pthread_cond_timedwait()代わりに を使用します。

于 2012-07-02T07:22:24.647 に答える