【问题标题】:Unaligned issue about ether_addr_equal function?关于 ether_addr_equal 函数的未对齐问题?
【发布时间】:2016-09-20 15:57:59
【问题描述】:

我正在阅读一些关于未对齐内存访问问题的文章并参考了这篇文章UNALIGNED MEMORY ACCESSES

bool ether_addr_equal(const u8 *addr1, const u8 *addr2) {
    #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
    u32 fold = ((*(const u32 *)addr1) ^ (*(const u32 *)addr2)) |
       ((*(const u16 *)(addr1 + 4)) ^ (*(const u16 *)(addr2 + 4)));
    return fold == 0;
    #else
    const u16 *a = (const u16 *)addr1;
    const u16 *b = (const u16 *)addr2;
    return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0;
    #endif
}

它说:

但是当硬件不是 能够访问任意边界上的内存,对 a[0] 的引用导致 从地址 addr1 开始的内存中读取 2 个字节(16 位)。

好吧,我不知道这意味着什么。在我看来,a[0] 必须从 addr1 读取 2 个字节,如果不是,它将读取什么? (可能会崩溃,但我认为这是 2 个字节或没有的情况)。那么这里会出现什么问题呢?而他们为什么不使用u8*,逐字节比较来解决未对齐的问题呢?

【问题讨论】:

    标签: c linux linux-kernel linux-device-driver


    【解决方案1】:

    在我看来,a[0] 必须从 addr1 读取 2 个字节,如果不是,它将读取什么?那么这里会出现什么问题呢?

    预期的含义当然是a[0] 使用 2 字节访问从 addr1 读取一个字节,从 addr1 + 1 读取一个字节。一个系统可能有一个限制,要求从偶数地址边界开始访问 2 字节。如果addr1 是奇数,那就违反了。

    而他们为什么不使用 u8* 一个字节一个字节地比较来解决未对齐的问题呢?

    可能假设目标系统不会遇到上述问题。一次使用一个字节就可以解决这种情况。


    注意:该功能的两半似乎功能不等效。考虑数据位全为零,第一个返回true,第二个返回false

    【讨论】:

    • “可能假设...” - 比这更好,addr1addr2 有效保证至少 16 位对齐:“它由调用者来确保这种对齐或根本不使用这个函数。”
    • @Notlikethat 由于该函数的两半具有不同的功能,我怀疑该函数的下半部分是否每个都真正使用过。
    • 确实,我敢肯定没有人会编译文档 ;) The real function itself is correct.
    • @chux 谢谢你的解释。但是如果 addr1 和 addr2 没有与 u16 对齐会发生什么?这取决于架构吗?
    • @cheneydeng 是的,取决于架构。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-03
    • 1970-01-01
    • 1970-01-01
    • 2015-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多