我有一些数据采集应用程序在带有TI Linux的DM8148上的Linux 2.6.37下运行.我有两个主题:
名为IDE的线程,调度为SCHED_RR,prio 114(75),每2ms从HW FIFO收集到达200MiB/s的数据到30MiB环形缓冲区:
while(1) {
sleep(ms);
while(DataInFIFO) {
CollectToRingBuffer();
SignalToWriter(); }
}
Run Code Online (Sandbox Code Playgroud)线程WriterIDE,调度为SCHED_RR,prio 113(74),将此环形缓冲区写入USB盘上.
while(1) {
WaitForSignal();
writeToFileOnDOK();
}
Run Code Online (Sandbox Code Playgroud)我从write()功能测量中知道,有时这个USB写入可能会"挂起"大约1.5秒甚至2秒,试图写入DOK.但我确信,当我给收集器任务30MiB,足够150s时,一切都会好的.
没有!它不是!
我把时间测量代码.而我所看到的是,当作者挂了很长时间(fe1342ms),然后进入收集器线程时间也非常大(306ms).这会导致HW FIFO溢出和数据不一致.
我检查了系统中线程优先级的传播(ps命令) - 没有什么是实时的,除了我.所有系统任务都被安排为OTHER(ps输出中的TS),甚至是内核USB线程.只有IRQ任务是FF,但即使它们的优先级较低.
我不知道从哪里去...... :-(
SHORT:我不能找到一种方法,mmap在O_WRONLY打开的文件.
LONG:我正在寻找尽可能快地将DMA(s/g模式)提供的数据写入磁盘PARTITION(!),避免内核缓冲的方法.O_DIRECT不起作用,Linus禁止使用它.
为此我在mmap每个DMA缓冲区中都有MAP_FIXED和文件中相应的偏移量.但是如果文件被打开O_RDWR,这会导致内核在使用文件数据填充输入RAM时与DMA竞争.在大多数情况下,内核获胜... :)
所以,我需要向内核解释,它不应该触摸我的页面,只是在我调用时将它们写入映射文件msync().怎么样?
在嵌入式编程中,当描述硬件时,通常需要将结构元素放置在HW工程师设计它们的已知预定义位置.例如,让我们定义一个结构FPGA,它有大约100个寄存器/区域,如下面的简化示例所示:
struct __attribute__ ((__packed__)) sFPGA {
uchar Spare1[0x24];
ushort DiscreteInput;
uchar Spare2[0x7A];
//CPLD_Version is required to be at offset 0xA0, so 0xA0-0x24-2=0x7A
ushort CPLD_Version;
};
Run Code Online (Sandbox Code Playgroud)
现在,我对手动计算感到沮丧和愤怒,并且在结构发生变化时可能出现错误.有没有办法做得更健壮/方便?我试着这样写:
uchar Spare2[0xA0 - offsetof(sFPGA, Spare2)];
Run Code Online (Sandbox Code Playgroud)
但这不会编译抱怨不完整的结构...注意,我的例子是简化的.实际上,必须定义大约20-30个这样的备用字段 - 结构非常大.
我需要在嵌入式 Linux(2.6.37) 中尽可能快地将传入的 DMA 缓冲区写入到 HD 分区作为原始设备 /dev/sda1。缓冲区按要求对齐,长度相等,为 512KB。该过程可能会持续很长时间并填充多达例如 256GB 的数据。我需要使用内存映射文件技术(O_DIRECT 不适用),但无法理解如何执行此操作的确切方法。所以,在伪代码“正常”写作中:
fd=open(/dev/sda1",O_WRONLY);
while(1) {
p = GetVirtualPointerToNewBuffer();
if (InputStopped())
break;
write(fd, p, BLOCK512KB);
}
Run Code Online (Sandbox Code Playgroud)
现在,我将非常感谢如何利用内存映射技术编写本文的类似伪/真实代码示例。
UPDATE2:感谢 kestasx,最新的工作测试代码如下所示:
#define TSIZE (64*KB)
void* TBuf;
int main(int argc, char **argv) {
int fdi=open("input.dat", O_RDONLY);
//int fdo=open("/dev/sdb2", O_RDWR);
int fdo=open("output.dat", O_RDWR);
int i, offs=0;
void* addr;
i = posix_memalign(&TBuf, TSIZE, TSIZE);
if ((fdo < 1) || (fdi < 1)) {
printf("Error in files\n");
return -1; }
while(1) {
addr = mmap((void*)TBuf, TSIZE, PROT_READ …Run Code Online (Sandbox Code Playgroud) 在我的基于ARM的主板(DM368)的u-boot中,我手动将某些内核分区块标记为坏.U-boot说它被标记,例如,在写/读内核图像时,我看到它跳过这个坏块.
但是当我尝试从Linux中编写相同的分区(通过NFS加载)时,我看到Linux nandwrite命令使用了这个坏块!我通过几种方式检查了这一点 - Linux忽略了100%的坏块标记.但是在互联网上的每个地方都说BBT是u-boot和Linux的一部分.
那么,捕获量在哪里?