代码之家  ›  专栏  ›  技术社区  ›  Oliver Charlesworth

C语言中不破坏严格别名和对齐的消息分派系统

  •  2
  • Oliver Charlesworth  · 技术社区  · 15 年前

    我正在用C编写一个嵌入式控制系统,它由多个相互发送消息的任务组成(我相信这是一个相当常见的习惯用法!),但我很难设计一种机制:

    • 整洁
    • 是通用的
    • 最重要的是: 与平台无关(特别是不违反严格的别名或对齐问题)

    void sendMsg(queue_t *pQueue, void *pMsg, size_t size);
    void *dequeueMsg(queue_t *pQueue);
    

    哪里 queue_t 包含节点的链接列表,每个节点都有一个 char buf[MAX_SIZE] 领域我使用的系统没有 malloc()

    1. sendMsg() 做一个 memcpy 将传入消息放入空闲节点的缓冲区。
      dequeueMsg() 进一步 memcpy 关于返回值。
    2. 否则会有一个 void *getFreeBuffer() 函数,该函数返回 buf[] 调用方(发送方)将其转换为指向类型的适当指针的下一个空闲节点的。
      memcpy 之后 dequeueMsg() 以避免在退出时出现对齐问题。
    3. 或者在中重新定义缓冲区 节点作为(例如) uint32_t buf[MAX_SIZE] .
      我的理解是,这违反了严格的别名,并且与平台无关。

    ,但我不认为这是“整洁”!

    所以我的问题是,如何正确地做到这一点?

    2 回复  |  直到 15 年前
        1
  •  2
  •   Crashworks    15 年前

    我们处理这个问题的方法是让空闲列表完全由对齐的节点组成。事实上,对于不同大小的节点,我们有多个空闲列表,因此我们有在2字节、4字节和16字节边界上对齐的列表(我们的平台不关心大于一个SIMD向量的对齐)。任何分配都会向上舍入到这些值之一,并放入一个正确对齐的节点中。因此,sendMsg总是将其数据复制到对齐的节点中。由于您自己编写自由列表,因此可以轻松地执行对齐。

    我们还将使用#pragma或declspec强制char buf[MAX#u SIZE]数组至少与队列节点结构内的字边界对齐。

    期望 要(比方说)偏离对齐3个字节,您始终可以使用模数检测到它,并将偏移量返回到空闲节点。

        2
  •  1
  •   DaveR    15 年前

    我不明白为什么 显示对齐问题-只要每个 buf[MAX_SIZE] 元素与消息结构中出现的自然最大的单一基元类型(可能是32位或64位)对齐,那么每个消息类型的内容是什么并不重要;因为它将始终与该尺寸对齐。

    MAX_SIZE 在长度上,然后假设每个消息都以自己的格式开始 buf