2016-04-13 45 views
-1

私はいくつかの変数を共有する必要があるPthreadを使ってCプロジェクトに取り組んでいます。いくつかのコード行がまだ書かれていますが、共有グローバル変数を使用するとキャッシュシステムのためにはうまく動作しないことに気付きました。PthreadはCでポインタを持つ変数を共有します

解決策は、変数(私の場合は2つ以上あります)のアドレスをスレッド関数に渡すことです。何が変わるのですか?

私のスレッド関数はグローバルを変更する他の関数を呼び出しているので、ある関数がグローバルを変更する関数の連鎖にパラメータを追加するのは少し面倒です。

私は、各グローバルのグローバルポインタを宣言し、それらを使用して実際のグローバルの代わりにグローバルにアクセスするのかどうか疑問に思っていましたか?

私はそれが表面的なインデルダクションだと思っていますが、なぜそれはまったく機能しないのですか?

私のプログラムは、リングネットワークやリング状の単純リンクリストのようなUDPネットワークプロトコルです。ネットワーク上のプログラムのインスタンスはエンティティと呼ばれます。

エンティティエンティティは、リングに挿入することも、エンティティに別のリング(dupplication)を作成するように依頼することもできます。したがって、もう一方のエンティティは2つのリングになります。

インターフェイスは、コマンドがリング上でメッセージを送信することができるシェルの一種です。メッセージは、今まで見たことがあるときに停止した後、すべてのリングに点在します。

シェルはメインスレッドにあり、メッセージ処理のためのスレッドと、挿入を管理するスレッドと、壊れたリングを検出するスレッドがあります。問題はリングテスタースレッドにあります。スレッドは、エンティティの最大リング番号のサイズのグローバル配列(volatile short ring_check[NRING])を初期化し、実際のリング数に応じて最初の要素を0で初期化し、残りを-1でリングごとにテストメッセージを送信した後で初期化します30秒のタイムアウト中にスリープします。タイムアウトが終了すると、配列内の値がチェックされます。

メッセージ処理のためにスレッドによって値が変更されます。テストメッセージが戻ったときに内容で検出され、ring_check要素に-1と書き込まれます。

問題は、dupplicationの後、2つのリングがテストされますが、2番目のリングのチェックに失敗しました(ring_check[1] == 0)、なぜ実際にはわからないのですか?テストメッセージは、 ring_check[1]0に変更して、実際に変更が行われたかどうかを確認して印刷します.1〜20秒後にはring_testerが覚醒し、0ring_check[1]となります。

short volatile ring_check[NRING+1]; 

// The function in the ring tester thread 
static void test_ring() { 
    // initialize ring_check array 
    debug("ring_tester", GREEN "setting ring_check to -1..."); 
    char port_diff[5]; 
    // send test messages in each rings 
    int fixed_nring = getnring(); 
    for (int i = fixed_nring+1; i < NRING; ++i) { 
     ring_check[i] = -1; 
    } 
    for (int i = 0; i < fixed_nring + 1; i++) { 
     debug("ring_tester", GREEN "setting ring_check %d to 0...", i); 
     ring_check[i] = 0; 
     itoa4(port_diff, ent.mdiff_port[i]); 
     debug("ring_tester", GREEN "sending test to ring %d...", i); 
     sendmessage(i, "TEST", "%s %s", ent.mdiff_ip[i], port_diff); 
    } 
    debug("test_ring", GREEN "timeout beginning..."); 
    sleep(timeout); 
    debug("test_ring", GREEN "end of timeout."); 

    for (int i = 0; i < fixed_nring + 1 && ring_check[i] != -1; i++) { 
     debug("test_ring", GREEN "ring_check[%d]:%d", i, ring_check[i]); 
     if (ring_check[i]) { 
      debug("test_ring", GREEN "ring %d: checked.", i); 
      continue; 
     } 
     else { 
      debug("test_ring", GREEN "ring %d: checking failed. Ring broken...", i); 
      continue; 
     } 
    } 


// The function called by the message treatment thread 

static int action_test(char *message, char *content, int lookup_flag) { 
    debug("action_test", RED "entering function..."); 
    if (content[15] != ' ' || content[20] != 0) { 
     debug("action_test", RED "content not following the protocol."\ 
       "content: \"%s\"", content); 
     return 1; 
    } 
    if (lookup_flag) { 
     char mdiff_port[5]; 
     int fixed_nring = getnring(); 
     for (int i = 0; i < fixed_nring + 1 && ring_check[i] != -1; ++i) { 
      itoa4(mdiff_port, ent.mdiff_port[i]); 
      // find ring associated with message and actualize the checking 
      if (strncmp(content, ent.mdiff_ip[i], 15) == 0 && 
        strncmp(&content[16], mdiff_port, 4) == 0 && 
        ring_check[i] != -1) { 
       ring_check[i] = 1; 
       debug("action_test", 
         RED "correspondance found, ring_check[%d]:%d", i, ring_check[i]); 
       return 0; 
      } 
     } 
    } 
    else { 
     sendpacket_all(message); 
    } 
    return 0; 
} 
+1

"共有グローバル変数を使用すると、キャッシュシステムのためにうまく動作しません"とはどういう意味ですか、共有オブジェクトへのポインタではどう違うのですか? – EOF

+0

私はあなたが 'volatile 'キーワード(http://stackoverflow.com/questions/78172/using-cpthreads-do-shared-variables-need-to-be-volatile)を使わないと話していました。変数が「揮発性」と宣言されているので、私がそれを言ったとき、私は混乱しました。この問題は静的に割り当てられた配列 'volatile short ring_check [10]'に現れます。これはスレッドによって変更されますが、別のスレッドはそれを読み込み、変更が見られません。 –

+1

\ * sigh \ *。 「揮発性」は赤いニシンです。関連するものはC11ドラフト標準n1570、* 5.1.2.4マルチスレッド実行とデータ競争、4 2つの表現評価が競合するとメモリの場所が変更され、もう1つが同じメモリ位置を読み込んだり変更したりすると競合します。 ]プログラムの実行には、異なるスレッドに2つの競合するアクションが含まれていて、少なくとも1つがアトミックではなく、どちらもアトミックでない場合、データ競合が含まれます。そのようなデータ競合は、未定義の動作を引き起こします。*これはグローバルであるかどうかにかかわらず、*すべての*共有オブジェクトに影響します。 – EOF

答えて

0

thread_inputparamなどのグローバル構造を定義できます。すべてのグローバル変数のアドレスをその中に置き、この構造変数のアドレスであるすべてのスレッドに送信します。

int global1; 
struct thread_input { 
    int *g1; 
    // add other globals'addresses 
}thread_inputparam; 
thread_inputparam.g1=&global1; 
+0

はい、それは私が考えている最初のアイデアですが、スレッドの作成と変数がチェーンの最後にアクセスするだけなので、長いチェーンの関数があるので、コード内で多くのリファクタリングが発生します。チェーンの各機能にパラメータを追加するのはエレガントで、変数とは何の関係もありません。スレッドはグローバル変数にアクセスできますが、変数ごとにキャッシュコピーがあり、同時性の不一致が発生します。ですから、代わりにグローバルポインタを使用すると、そのメカニズムを欺くのだろうかと思います。 –

+0

キャッシュのコピーを明確に理解できません。これを明確にしてください。 –

+0

申し訳ありませんが、私は混乱していました。非揮発性変数で発生する可能性のある問題について考えましたが、私は考慮していません。 –

関連する問題