【问题标题】:Difference between crc32() implementations of <linux/crc32.h> and <zlib.h> in CC 中 <linux/crc32.h> 和 <zlib.h> 的 crc32() 实现之间的区别
【发布时间】:2017-03-17 22:51:22
【问题描述】:

我在char* s = "pratik" 上调用了两个函数:

用户代码:

#include <zlib.h>
int main()
{
    char *s = "pratik";
    printf("%x\n",crc32(0x80000000, s, strlen(s)));
    return 0;
}

输出: 66fa3c99

内核代码:

#include <linux/crc32.h>

int main()
{
    char *s = "pratik";

    u32 checksum = crc32(0x80000000, s, strlen(s));
    printk("\nChecksum --> %x", checksum);

    return checksum;
}

输出:

校验和 --> d7389d3a

为什么相同字符串的校验和值不同?

【问题讨论】:

  • strlen(6)... 你确定吗?
  • 除了代码中可能出现的错误之外,请记住,CRC 实际上是一个系列算法,由几个选项参数化(首先是摘要大小 - 始终为 32 位在您的情况下-还有使用的多项式、位字节序、初始化值,以及可以在算法的各个阶段执行的一些额外位操作)。鉴于内核实现是为计算网络数据包的 CRC 值而生的,我不会对它反转位字节序感到惊讶。关于 CRC 的一些有趣信息:ross.net/crc/download/crc_v3.txt.
  • 虽然生成多项式看起来相同(Linux 引用 ITU V.42,与 what zlib uses 相同,但在 linux/crc32.h 中有 little-endian and big-endian versions 的 crc32。你可以尝试调用crc32_be 而不是?
  • @mindriot 当我运行 crc32_be(s) 时,它会打印 B131FB25,它仍然与用户调用不匹配,并且 crc32_le(s) 会打印与内核程序的 crc32(s) 相同的值。
  • 也许您还需要更改种子值的字节顺序(可能将0x80000000 替换为0x00000080)?为确保种子不会导致问题,建议您将其设置为 0 并再次比较两个 crc32 版本。

标签: c++ c linux linux-kernel crc32


【解决方案1】:

似乎有人对标准以太网(PKZIP、ITU V.42 等)CRC-32 与0xffffffff 进行前排和后排的事实感到不安。因此,Linux 内核中的版本忽略了这一点,并希望应用程序能够做到这一点。去图吧。

无论如何,您可以使用(非标准)Linux crc32() 代替(正确的)zlib crc32() 获得相同的结果,因此:

crc_final = crc32(crc_initial ^ 0xffffffff, buf, len) ^ 0xffffffff;

事实上,完全相同的代码也允许您使用 zlib crc32() 复制 Linux crc32()。

【讨论】:

  • 天才之笔!谢谢你,真的。多年来一直在做这个!
猜你喜欢
  • 1970-01-01
  • 2015-03-18
  • 2015-11-20
  • 2012-10-04
  • 2015-06-27
  • 1970-01-01
  • 2020-04-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多