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() 实现之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

win32 多线程编程

win32 多线程编程

第二例:查看进程程序

IcmpBackDoor

深入浅出Flask(32): H-ui前端框架的警告窗口

扫描系统进程和获取某进程的PID