【问题标题】:how to perform data structure alignment with kmalloc?如何使用 kmalloc 执行数据结构对齐?
【发布时间】:2011-07-15 16:51:17
【问题描述】:

我一直在阅读 数据结构对齐 文章,但我一无所获。也许事情太复杂了,我无法理解。我还遇到了 数据结构填充,这也是对齐数据所必需的。如何向 struct usb_ep 添加数据结构填充?另外,我如何确保每当我执行 kmalloc 时,要读取的数据应该处于 4 的倍数的内存偏移量?

【问题讨论】:

    标签: c linux data-structures linux-kernel alignment


    【解决方案1】:

    关于对齐,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字节,无需添加填充。

    【讨论】:

    • 如果你使用 pragma pack 指令,是否意味着你不必做填充?
    • 是不是也意味着使用kmalloc,你就不用担心数据对齐了,因为它已经默认对齐数据了?
    • 当然不是! kmalloc() 对您尝试分配的数据的内部结构一无所知。
    • @Owen,kmalloc 将对齐数据,但您需要确保它不需要像我的示例中那样填充结构。例如,使用 pragma pack(1) 将完全阻止它添加填充,这意味着我的示例中的第一个和第二个 usb_ep 将具有相同的大小而不添加任何填充,并且您无需担心对齐和填充.
    【解决方案2】:

    来自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 个字节。一些编译器允许您指定在这种情况下会产生正确结果的打包结构。通常我只是声明从最大类型到最小类型的字段并保留它。如果您需要在两个语言/编译器之间共享内存,那么您需要确保这些结构在内存中对齐。

    【讨论】:

      猜你喜欢
      • 2019-02-08
      • 1970-01-01
      • 2017-02-17
      • 2013-06-03
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多