如何在堆栈上对齐缓冲区?

时间:2012-12-01 21:26:59

标签: c++ gcc embedded

我试图通过它的大小来实现一个对齐的内存缓冲区,这样我就可以使用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会相对有效吗?

有什么想法吗?

4 个答案:

答案 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.cpp
char 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兼容的缓冲区。