0

シナリオ:

  • ラズベリーパイ3モデルB
  • USB経由で接続されたAdaptronic Modular ECU(大容量記憶装置として表示されます。実際には2つ、この場合はsdaとsdbです)

私は単純に fopen() を使用して読み取り用に /dev/sda を開き、読み取りたい位置をシークして 2048 バイトを読み取りました。次に、以前にシークした位置に再シークし、そのデータを再度読み取ります。

最初の読み取りで、新鮮で正しいデータを取得します。後続の各読み取りで、同じデータを何度も取得します。最初の読み取り後にデバイスを再度ポーリングしようとはしませんが (アクティビティ ライトがあるため)、アプリを強制終了すると (ctrl + c)、アクティビティ ライトが激しく点滅して停止します。

私はそれが自分のコードのバッファリングの問題だと思っていました (私は ifstream から始めて、fopen() と open() をすべて同じように試しました)、バフを無効にするさまざまな方法 (つまり、setvbuf()) を試しましたが、私はまだ新しいデータを取得していません。

ファイルを閉じて再度開くと、新しいデータが得られますが、これは非常に遅いプロセスです (1 秒あたり約 10 ~ 12 サンプルしか得られません)。

これはマウントされたデバイスではなく、単にストレージ デバイスとして表示され、そのブロック デバイスから直接読み取ることに注意してください。

同じコードを Windows に移植したところ、動作するので、これは私のコードではなく、Linux 内の何かだと思います。

どんな助けでも大歓迎です。

4

1 に答える 1

2

これは、stackexchange サイトでの私の質問で解決されました: unix.stackexchange.com/questions/372452/disable-read-cache-buffer-for-usb-mass-storage-device-in-linux

要約すると、問題は、使用する必要があるO_DIRECTが、データの完全なブロックを読み取っている (および探している) ことを確認する必要があるということでした。私の場合、デバイスは 512 バイトのブロックにあったため、その量を取得する必要がありました。

#define NUM_VARS 1024
#define PAGE 4096
#define STARTBYTE (272384/PAGE*PAGE) // must align
#define OFFSET (272384-STARTBYTE)
#define ITEMSIZE (sizeof(*liveBuffer))
#define LIVEBUFSIZE ((OFFSET+NUM_VARS*ITEMSIZE+PAGE-1)/PAGE*PAGE)

signed short *liveBuffer;
FILE *input = fopen("/dev/sda", "r+");
if(posix_memalign((void**)&liveBuffer, PAGE, LIVEBUFSIZE)!=0)
   exit(5);
if (fcntl(fileno(input), F_SETFL, O_DIRECT) == -1)
   exit(6);
fseek(input, OFFSET, SEEK_SET);
fread(liveBuffer, ITEMSIZE, LIVEBUFSIZE, input);
fclose(input);
于 2017-06-26T10:08:34.603 に答える