私はいくつかの変数を共有する必要がある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
が覚醒し、0
はring_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;
}
"共有グローバル変数を使用すると、キャッシュシステムのためにうまく動作しません"とはどういう意味ですか、共有オブジェクトへのポインタではどう違うのですか? – EOF
私はあなたが 'volatile 'キーワード(http://stackoverflow.com/questions/78172/using-cpthreads-do-shared-variables-need-to-be-volatile)を使わないと話していました。変数が「揮発性」と宣言されているので、私がそれを言ったとき、私は混乱しました。この問題は静的に割り当てられた配列 'volatile short ring_check [10]'に現れます。これはスレッドによって変更されますが、別のスレッドはそれを読み込み、変更が見られません。 –
\ * sigh \ *。 「揮発性」は赤いニシンです。関連するものはC11ドラフト標準n1570、* 5.1.2.4マルチスレッド実行とデータ競争、4 2つの表現評価が競合するとメモリの場所が変更され、もう1つが同じメモリ位置を読み込んだり変更したりすると競合します。 ]プログラムの実行には、異なるスレッドに2つの競合するアクションが含まれていて、少なくとも1つがアトミックではなく、どちらもアトミックでない場合、データ競合が含まれます。そのようなデータ競合は、未定義の動作を引き起こします。*これはグローバルであるかどうかにかかわらず、*すべての*共有オブジェクトに影響します。 – EOF