【发布时间】:2011-07-15 16:51:17
【问题描述】:
我一直在阅读 数据结构对齐 文章,但我一无所获。也许事情太复杂了,我无法理解。我还遇到了 数据结构填充,这也是对齐数据所必需的。如何向 struct usb_ep 添加数据结构填充?另外,我如何确保每当我执行 kmalloc 时,要读取的数据应该处于 4 的倍数的内存偏移量?
【问题讨论】:
标签: c linux data-structures linux-kernel alignment
我一直在阅读 数据结构对齐 文章,但我一无所获。也许事情太复杂了,我无法理解。我还遇到了 数据结构填充,这也是对齐数据所必需的。如何向 struct usb_ep 添加数据结构填充?另外,我如何确保每当我执行 kmalloc 时,要读取的数据应该处于 4 的倍数的内存偏移量?
【问题讨论】:
标签: c linux data-structures linux-kernel alignment
关于对齐,kmalloc 将正确对齐结构。如果你有一个 4 字节的变量,它将是 4 字节对齐的,如果你有一个 8 字节的变量,它将是 8 字节对齐的。理解对齐是需要填充的原因。
您不想得到的是结构中变量之间的垃圾填充。您可以使用pragma pack directive(可能最简单)或手动添加填充来做到这一点。
例子
struct usb_ep
{
short a; /* 2 bytes*/
int b; /* 4 bytes*/
short c; /* 2 bytes*/
};
所有元素的大小为8bytes,但由于对齐要求,大小为12bytes。内存布局是这样的:
short a - 2 bytes
char pad[2] - 2 bytes of padding
int b - 4 bytes
short c - 2 bytes
char pad[2] - 2 bytes of padding
为了不得到任何填充,或增加结构的大小,您可以重新排列元素以满足对齐要求。
那是有一个结构:
struct usb_ep
{
short a; /* 2 bytes*/
short c; /* 2 bytes*/
int b; /* 4 bytes*/
};
大小为8字节,无需添加填充。
【讨论】:
来自http://minirighi.sourceforge.net/html/kmalloc_8c.html
void * kmemalign (size_t alignment, size_t size)
Allocate some memory aligned to a boundary.
Parameters:
alignment The boundary.
size The size you want to allocate.
Exceptions:
NULL Out-of-memory.
Returns:
A pointer to a memory area aligned to the boundary. The pointer is a aligned_mem_block_t pointer, so if you want to access to the data area of this pointer you must specify the p->start filed.
Note:
Use kfree(void *ptr) to free the allocated block.
在结构中填充字段的最佳方法是以递减的大小声明变量。所以首先是最大的,然后是最小的。
struct example {
double amount;
char *name;
int cnt;
char is_valid;
};
这并不总是以结构中逻辑连接的项目结束,但通常会提供最紧凑且易于访问的内存使用情况。
您可以在结构声明中使用填充字节,但它们会使代码混乱,并且不能保证结构紧凑。编译器可能会在 4 字节边界上对齐每个字节,因此您最终可能会得到
struct example2 {
char a;
char padding1[3];
char b;
char padding2[3];
};
a 占用 4 个字节,padding1 占用 4 个字节,b 占用 4 个字节,padding2 占用 4 个字节。一些编译器允许您指定在这种情况下会产生正确结果的打包结构。通常我只是声明从最大类型到最小类型的字段并保留它。如果您需要在两个语言/编译器之间共享内存,那么您需要确保这些结构在内存中对齐。
【讨论】: