我试图通过它的大小来实现一个对齐的内存缓冲区,这样我就可以使用DMA控制器的模数功能来实现一个环形缓冲区。我知道我可以用memalign做到这一点,但我想知道是否可以在堆栈上这样做,因为到目前为止,我已经能够避免动态内存。我使用的是GCC 4.4.1,我并不关心可移植性(嵌入式系统)。
我想做类似的事情:
template<uint16_t num_channels, uint16_t buffer_size>
class sampler {
__attribute__((aligned(buffer_size * num_channels * 2)))
uint16_t buffer[buffer_size][num_channels];
};
但当然GCC不会接受非恒定对齐(并且似乎表明对齐&gt; 8可能无法兑现)。
我想我可以使用C ++ 0x alignas()来实现这一点,但它似乎不会出现在GCC中直到4.8版本。
我猜一个选项可能是将缓冲区的大小加倍,但这似乎浪费了一大堆空间(我打算尝试将大部分设备内存用于此缓冲区)。也许我应该放弃并使用动态内存。在浪费的空间方面,memalign会相对有效吗?
有什么想法吗?
答案 0 :(得分:5)
您不需要将存储空间的大小加倍,您只需要向其添加(alignment - 1)
- 基本上与memalign
幕后操作相同。对于两个对齐的力量:
char buf[size + (alignment -1)];
char *aligned = (char*)((intptr_t)buf + (alignment - 1) & ~intptr_t(alignment - 1));
答案 1 :(得分:1)
我使用链接器命令文件已经很长时间了,但我认为它会像这样。
使用
创建文件buffer.cppchar buffer[ BUFFER_SIZE ];
目标文件包含名为.bss(用于未初始化数据),。数据(用于初始化数据)和.text(用于可执行代码)的部分。 buffer []将进入.bss,因为它没有被初始化。
所以像这样的(gnu)链接器文件应该可以解决这个问题
SECTIONS {
.bss 0x0 : {
buffer.o(.bss)
*(.bss)
}
.data : {
*(.data)
}
.text : {
*(.text)
}
}
0x0告诉链接器在地址0x0加载缓冲区[]。
答案 2 :(得分:0)
你能创建一个大于buffer_size
的缓冲区,然后计算一个从中开始的偏移吗?
答案 3 :(得分:0)
如果您的嵌入式系统有内存管理单元,则无需担心明智地使用动态内存,尤其是每次运行只分配一次。
如果它没有MMU,您可以考虑使用链接器映射文件分配固定位置。
在具有实际操作系统的系统上,无论如何都可能必须由内核专门分配与DMA兼容的缓冲区。