1

大きなメモリ バッファを割り当てるカーネル モジュールがあり、このバッファはユーザー空間に mmap されます。
モジュールはハードウェアからいくつかのデータを受信し、その前にフラグを付けて新しいデータをバッファに入れます。(メモリはゼロに初期化され、フラグは 1)。

ユーザー空間プログラムは、有効なデータへのポインターを返す前にループでフラグを読み取ります

コードの簡略版:

uint8_t * getData()
{
    while(1)
   {
      if(*((volatile uint32_t*)this->buffer) == 1)
          return this->buffer+sizeof(uint32_t);
   }
}

メモリ領域は共有としてマップされ、フル バッファ メモリ ダンプにより、バッファが正しく書き込まれていることが確認されます。

問題は、一定数の正しい読み取りの後、この関数が戻りを停止することです。
これはCPUキャッシングが原因でしょうか?それを回避し、読み取りがキャッシュからではなく RAM から毎回直接行われるようにする方法はありますか?

4

2 に答える 2

0

はい、リーダー側の CPU キャッシュが原因である可能性があります。「volatile」キーワードはこの種の問題から保護する必要があると考えるかもしれませんが、それは正しくありません。なぜなら、volatile は変数を登録しないようにコンパイラに指示するだけであり、CPU にメイン メモリから直接読み取るように指示することとはまったく同じではないからです。毎回。

この問題は書き込み側で解決する必要があります。あなたの説明から、カーネルモジュールで書き込みが行われ、ユーザー側から読み取られているように聞こえます。これらの 2 つの操作が異なる CPU (異なるキャッシング ドメイン) で行われており、読み取り側でキャッシュの無効化をトリガーするものが何もない場合、説明しているように読み取り側でスタックします。ストア命令の後に、Linux カーネルでストア バッファ フラッシュを強制する必要があります。それが Linux カーネルであると仮定すると、フラグとモジュールからの値を設定した直後に smp_mb への呼び出しを挿入すると、すべてのアーキテクチャで正しいことが行われる可能性が高くなります。

于 2012-02-08T00:04:36.070 に答える
0

より多くのデータが存在することをユーザー空間アプリケーションに警告するより良い方法はread()、カーネル モジュールによって提供されるファイル記述子をブロックし、より多くのデータが利用可能になったときにカーネル モジュールがアプリケーションを起動することです。

于 2012-02-08T00:36:11.087 に答える