我正在为SparkFun Logomatic V2编写自定义固件,该固件将二进制数据记录到2GB micro SD卡上的文件中。数据文件的大小范围从100 MB到1 GB。
二进制数据的格式随着板固件的发展而不断变化(它实际上在运行时可以动态重新配置)。与其为每个版本的固件/配置创建和维护单独的解码器/转换器程序,我更愿意通过在数据记录开始前用Bash脚本启动数据文件,使数据文件自行转换为CSV格式。
我知道如何创建Here Document,但我怀疑Bash无法快速解析和转换千兆字节的二进制数据,所以我想让脚本首先编译一些C代码(假设GCC存在并且在路径中),然后运行生成的程序,将二进制数据传递到stdin,从而使进程运行得更快。
为了使问题更加具体,假设固件将创建由4个16位整数值组成的二进制数据:一个时间戳(无符号),后跟3个加速度计轴(有符号)。记录之间没有分隔符(主要是因为我正在饱和uSD卡的SPI接口)。
因此,我认为我需要一个包含两个文档的脚本:一个用于C代码(由扩展的Bash变量参数化),另一个用于二进制数据。这是我目前的处境:
#! env bash
# Produced by firmware version 0.0.0.0.0.1 alpha
# Configuration for this data run:
header_string = "Time, X, Y, Z"
column_count = 4
# Create the converter executable
# Use "<<-" to permit code to be indented for readability.
# Allow variable expansion/substitution.
gcc -xc /tmp/convertit - <<-THE_C_CODE
#include <stdio.h>
int main (int argc, char **argv) {
// Write ${header_string} to stdout
while (1) {
// Read $(column_count} shorts from stdin
// Break if EOF
// Write $(column_count} comma-delimited values to stdout
}
// Close stdout
return 0;
}
THE_C_CODE
# Pass the binary data to the converter
# Hard-quote the Here tag to prevent subsequent expansion/substitution
/tmp/convertit >./$1.csv <<'THE_BINARY_DATA'
...
... hundreds of megabytes of semi-random data ...
...
THE_BINARY_DATA
rm /tmp/convertit
exit 0
这看起来对吗?我还没有一个真正的数据文件来测试这一点,但我想在进一步研究之前验证一下这个想法。
如果最后几行不见了,Bash会抱怨吗?如果由于电池或uSD卡受到冲击而导致数据捕获意外终止,则可能会发生这种情况。或者固件出现故障。
有没有更快或更好的方法我应该考虑?例如,我想知道Bash是否会太慢,无法像C程序那样快速地复制二进制数据:C程序应该直接打开数据文件吗?
TIA,
-BobC
您可能需要了解makeself。它允许您将任何.tar.gz存档更改为独立于平台的自提取文件(类似于包含here文档的shell脚本)。这将允许您轻松地分发数据和解码器。它还允许您将包含在归档中的脚本配置为在运行容器脚本时运行。通过这种方式,您可以使用makeself进行打包,并在归档中放入用C或bash或任何您认为合适的语言编写的数据文件和解码器。
虽然可以使用shell工具(例如使用od
)解码二进制数据,但它非常繁琐且无效。我建议使用C程序或perl,这在几乎任何机器上都可以找到(请查看本页)。