C 中 <linux/crc32.h> 和 <zlib.h> 的 crc32() 实现之间的区别
Posted
技术标签:
【中文标题】C 中 <linux/crc32.h> 和 <zlib.h> 的 crc32() 实现之间的区别【英文标题】:Difference between crc32() implementations of <linux/crc32.h> and <zlib.h> in C 【发布时间】: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
版本。
【参考方案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()
。
【讨论】:
天才之笔!谢谢你,真的。多年来一直在做这个!以上是关于C 中 <linux/crc32.h> 和 <zlib.h> 的 crc32() 实现之间的区别的主要内容,如果未能解决你的问题,请参考以下文章