0

私のコードにはバッファがあり、それにデータを追加するコードは次のとおりです。

bool push_string(file_buffer *cb, const char* message, const unsigned short msglen)
{
    unsigned int size = msglen;

    if(cb->head >= (cb->size - size))
    {
        size = cb->size - cb->head - 1;
    }

    if(size < 1) return false;

    char* dest = cb->head += size;

    memcpy(dest, message, size);

    return (size == msglen);
}

複数の割り込み (互いに除外できる) からデータを追加するので、このコードがスレッドセーフかどうか疑問に思っていました。'cb->head' を volatile とマークしましたが、'head' の増加と 'dest' への代入の間で別の割り込みが正確に除外されると、問題が発生する可能性があります。

このコードを改善して安全性を高めるにはどうすればよいですか?

編集:「スレッドセーフ」という用語を使用すべきではなかったのかもしれません。並列で実行されているスレッドはなく、割り込みの可能性があるだけだからです。

4

2 に答える 2

0

信号を中断する信号について考えてください...本当に必要な場合:

push_string() を使用している間は、関連するすべてのシグナルをブロックできます。

アプリケーションに依存する別の可能性は、シグナル ハンドラ コードをメインの「スレッド」に移動することです (シグナル ハンドラ コードは、実行のメイン スレッドをウェイクアップする「イベント」を生成するだけです)。あなたのアプリが良い選択であるかどうかを判断するのに十分な情報がありません.

于 2013-01-21T11:07:46.710 に答える
0

C99 にはスレッドの概念がないため、スレッド保存の概念もありません。C11だけあります。C99 では、割り込みに対して安全な唯一のデータ型は ですがsig_atomic_t、明らかにこれはスレッドについても何も言いません。

一般に、データ構造に同時にアクセスしようとするのは完全に間違っており、volatile適切なデータを受け取るという保証はまったくありません。C11であっても、操作の原子性自体は保証されていないため、たとえば、ポインター値の下半分は既に書き込まれているが、上半分は書き込まれていないという状況になる可能性があります。これにより、完全に偽の結果が得られる可能性があります。このようなことはおそらく 100 万回に 1 回、または特別な状況 (高負荷など) で発生するため、追跡が非常に困難なバグにつながる可能性があります。

そうしないでください。

C11 は、そのようなこと、特にアトミック操作を処理するための新しいツールを提供します。完全に実装されているわけではありませんが、多くのコンパイラには既に役立つ拡張機能があります。これらのいくつかをP99マクロ パッケージにラップしたので、今日から特定のコンパイラでこれらの機能を使い始めることができます。

于 2013-01-21T10:20:15.510 に答える