大容量記憶装置としてUSBデバイスがあり、dmesgは次のようになります。
[ 4.416584] scsi 0:0:0:0: Direct-Access Adap ECU Modular ECU 1.0 PQ: 0 ANSI: 2
[ 4.420186] sd 0:0:0:0: [sda] 131072 512-byte logical blocks: (67.1 MB/64.0 MiB)
[ 4.421063] sd 0:0:0:0: [sda] Write Protect is off
[ 4.421084] sd 0:0:0:0: [sda] Mode Sense: 03 00 00 00
[ 4.422053] sd 0:0:0:0: [sda] No Caching mode page found
[ 4.422067] sd 0:0:0:0: [sda] Assuming drive cache: write through
[ 7.446823] sd 0:0:0:0: Attached scsi generic sg0 type 0
ファイルシステムを含めず、含めることはできません。インストールする必要はありません。 (この場合) /dev/sda を開いて読んでください。
問題は、デバイスを開いて読み込むときに最初に必要なものを取得し、その後のすべての読み取りからキャッシュされたデータを取得することです。デバイスのIOインジケータは、後続の読み取り後に点滅せず、最初の読み取りでのみ点滅するため、この仮定を行っています。もちろん、fread()
最初の読み取りとまったく同じデータが含まれているからですfread()
。
私のコードはWindowsでコンパイルし、\.\X:を開くファイルとして指定し、呼び出すたびに新しいデータでデータをうまくポーリングするため、問題はありません。
だから私はLinuxが読み取りをキャッシュ/バッファしていると仮定します。
私のコードは次のとおりです
#define STARTBYTE 272384
#define ENDBYTE 274432
#define NUM_VARS 1024
int main() {
FILE *input = fopen("/dev/sda", "r+");
setbuf(input, NULL);
int exit = 0;
while (exit < 1) {
signed short liveBuffer[NUM_VARS];
fseek(input, STARTBYTE, SEEK_SET);
fread(liveBuffer, 2, NUM_VARS, input);
fflush(input);
// do stuff with the now filled liveBuffer data
}
fclose(input);
return 0;
}
私も使用してopen()
指定してみましたO_DIRECT
が、違いはありませんでした。
これを行うには、デバイス(/ dev / sda)を開き、272384バイトを見つけます。 2048バイトを読みます。同じ位置を再度見つけて2048バイトを読むなどの作業をします。
fclose()
ファイルを再保存すると、open()
新しいデータが得られます。非常に遅いのではない場合です。 Windowsでは、(オンまたはオフにせずに)毎秒約10のサンプルを取得します。毎秒約50を取得します。
私が気づいたことの1つは、コンパイルされたコードを数秒間実行してから終了したら(CTRL + C)、コードの実行中にデバイスのアクティビティインジケータが狂ったように点滅することを示していることです。
誰もが正しい方向に私を指すことができますか?
数日間、このような考えをして首を結ぶべきだと思いました。
答え1
介入を使用すると、問題が少し複雑になります。標準入出力呼び出している関数の戻りコードを無視してください。これを使用してO_DIRECT
デバイスから新しいデータを取得できますが、それに応じた義務を遵守する必要があります。
具体的には、サーチオフセット、バッファアドレス、およびI / Oサイズはすべて4096の倍数(またはデバイスに応じて2の累乗)でなければなりません。
現在のliveBuffer宣言を削除し、最初に次のコードを含めるようにコードを変更すると、正しく機能することがわかります。
#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;
if(posix_memalign((void**)&liveBuffer, PAGE, LIVEBUFSIZE)!=0)
exit(5);
if (fcntl(fileno(input), F_SETFL, O_DIRECT) == -1)
exit(6);
fread()
代わりにNUM_VARSを使用する必要がありますLIVEBUFSIZE/ITEMSIZE
。ソートが必要なので、必要なデータを見つけるには配列にSTARTBYTE
さらに入る必要があります。また、すべての呼び出しを変更して戻りコードが正しいことを確認する必要があります。liveBuffer
OFFSET/ITEMSIZE