在 Linux 中为 USB 大容量存储设备禁用读取缓冲
Disabling read buffering in Linux for USB mass storage device
场景:
- Raspberry Pi 3 型号 B
- 通过 USB 连接的 Adaptronic 模块化 ECU(显示为大容量存储设备,实际上是 2,在本例中为 sda 和 sdb)
我只是简单地使用fopen()打开/dev/sda进行阅读,我寻找到我想阅读的位置,我阅读了2048字节。然后我重新寻找我之前寻找的位置并再次读取该数据。
第一次阅读时,我得到了新鲜、正确的数据。在随后的每次读取中,我一遍又一遍地得到相同的数据。第一次读取后,它不会尝试再次轮询设备(因为它有一个 activity 灯),但是当我终止我的应用程序 (ctrl+c) 时,我看到 activity 灯疯狂闪烁,然后停止。
我认为这是我的代码的缓冲问题(我从 ifstream 开始,并尝试了 fopen() 和 open(),都是一样的)并尝试了各种不同的禁用缓冲的方法(即 setvbuf ()) 但我仍然没有得到新数据。
如果我关闭并再次打开文件,我会得到新数据,但这是一个非常缓慢的过程(我只得到大约 10-12 samples/sec)。
请记住,这不是挂载设备,它只是作为存储设备出现,我直接从其块设备中读取。
我将相同的代码移植到 Windows 并且它可以工作,所以我不认为这是我的代码,而是 Linux.
中的一些东西
如有任何帮助,我们将不胜感激。
我在 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);
场景:
- Raspberry Pi 3 型号 B
- 通过 USB 连接的 Adaptronic 模块化 ECU(显示为大容量存储设备,实际上是 2,在本例中为 sda 和 sdb)
我只是简单地使用fopen()打开/dev/sda进行阅读,我寻找到我想阅读的位置,我阅读了2048字节。然后我重新寻找我之前寻找的位置并再次读取该数据。
第一次阅读时,我得到了新鲜、正确的数据。在随后的每次读取中,我一遍又一遍地得到相同的数据。第一次读取后,它不会尝试再次轮询设备(因为它有一个 activity 灯),但是当我终止我的应用程序 (ctrl+c) 时,我看到 activity 灯疯狂闪烁,然后停止。
我认为这是我的代码的缓冲问题(我从 ifstream 开始,并尝试了 fopen() 和 open(),都是一样的)并尝试了各种不同的禁用缓冲的方法(即 setvbuf ()) 但我仍然没有得到新数据。
如果我关闭并再次打开文件,我会得到新数据,但这是一个非常缓慢的过程(我只得到大约 10-12 samples/sec)。
请记住,这不是挂载设备,它只是作为存储设备出现,我直接从其块设备中读取。
我将相同的代码移植到 Windows 并且它可以工作,所以我不认为这是我的代码,而是 Linux.
中的一些东西如有任何帮助,我们将不胜感激。
我在 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);