在Linux中为USB大容量存储设备禁用读缓冲

时间:2017-06-21 00:07:52

标签: c++ linux raspberry-pi usb usb-mass-storage

情景:

  • Raspberry Pi 3 Model B
  • 通过USB连接的Adaptronic模块化ECU(本身就是一个大容量存储设备,实际上是2个,在这种情况下是sda和sdb)

我只是使用fopen()来打开/ dev / sda进行读取,我寻找我想要读取的位置并读取2048字节。然后,我重新寻找我之前寻找的位置并再次阅读该数据。

在我第一次阅读时,我获得了新鲜,正确的数据。在每次后续读取时,我会一遍又一遍地获得相同的数据。在第一次读取后,它不会再次尝试轮询设备(因为它有一个活动指示灯),但是当我杀死我的应用程序(ctrl + c)时,我看到活动指示灯疯狂闪烁然后停止。

我认为这是我的代码缓存问题(我从ifstream开始,尝试了fopen()和open(),都是这样)并尝试了各种不同的禁用缓冲方法(即setvbuf()) )但我还没有获得新数据。

如果我再次关闭并打开文件,那么我会获得新数据,但这是一个非常缓慢的过程(我只能获得大约10-12个样本/秒)。

请记住,这不是一个已安装的设备,它只是作为存储设备呈现,我直接从其块设备读取。

我将相同的代码移植到Windows并且它可以工作,因此我不相信这是我的代码,而是Linux中的内容。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

我在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);