1

我正在尝试cksum使用 Boost.CRC 实现简单的 POSIX。

我使用的代码相当于:

for(int i = 1; i<argc; ++i)
{
  support::file current(argv[i], support::file::access::read);
  size_t octets = 0;
  boost::crc_32_type crc;
  while(true)
  {
    size_t bytes_read = current.read_some(buffer_size, buffer);
    octets += bytes_read;
    crc.process_bytes(&buffer[0], bytes_read);
    if(bytes_read < buffer_size)
      break;
  }
  if(i>1)
    support::print("\n");

  support::print(boost::lexical_cast<string>(crc.checksum()) + " " + boost::lexical_cast<string>(octets) + " " + argv[i]);
}

哪里support::file是一个简单fopen/fread二进制文件 I/O 包装器,我成功地用于cat实现。support::print提供与 相同的输出std::cout,但我需要它在 Windows 上进行可靠的非 ASCII 输出。

Boost 标头有这个:

typedef crc_optimal<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true> crc_32_type;

作为唯一的 32 位 CRC typedef。cksum它为空文件 ( )给出了错误的答案(使用 GNUWin32 coreutils 检查touch test && cksum test)。我尝试使用上述 typedef 并将其中一个或两个0xFFFFFFFF值修改为 0,我得到了空文件的正确结果,但任何其他文件仍然给出不同的结果。

Boost.CRC 与POSIXcksum规范有何关系?

4

1 回答 1

1

这并不是对您问题的真正答案,而是我进行的调查的结果。当我用 VHDL 构建以太网控制器的简单实现时,我曾经与 CRC 作斗争,但我确实意识到,由于未知的原因,实现有时会非常不同。

好的,让我们开始吧。typedef您在以下位置找到的boost/crc.hpp

typedef crc_optimal<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true> crc_32_type;

是 CRC 生成器的简单声明,它将为以太网生成 CRC。模板的参数如下:(Bits生成器输出的位数),TruncPoly(生成器使用的多项式),InitRem(在处理输入的第一个字节之前要输入算法的初始余数),FinalXorXORed处理输入的所有字节后输出值应具有的值),ReflectIn以及ReflectRem(如果输入字节和/或输出应进行位反射,例如位 0 变为位 7,依此类推)。以太网不仅需要使用给定的多项式计算输出,而且还需要可以从 typedef 中读取的约束。

根据规范cksum,它的 CRC 生成器的 typedef 应该如下所示:

typedef crc_optimal<32, 0x04C11DB7, 0, 0xFFFFFFFF, false, false> cksum_crc_type;

这是因为 :

  • 规范没有指定生成器的起始值,因此为 0。
  • 根据规范的第 4 条,输出值应进行补码。通过将值与 1 进行异或,可以获得相同的结果。
  • 位反射在任何地方都没有提到,因此不会执行。

但是,cksum与普通 CRC 相比,存在一个显着差异:

(...) 后跟一个或多个八位位组,将文件的长度表示为二进制值,最低有效八位位组在前。应使用能够表示该整数的最小八位字节数。

普通 CRC 生成器不考虑已处理的八位字节数。这也可以解释为什么在处理零长度文件时会得到好的结果,但在处理较大的文件时会得到不好的结果。

不幸的是,我没有看到解决该问题的简单方法。我想你可以做的是通过process_bytes以下方式修改方法:

template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly,
           BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor,
           bool ReflectIn, bool ReflectRem >
inline
void
BOOST_CRC_OPTIMAL_NAME::process_bytes
(
    void const *   buffer,
    std::size_t  byte_count
)
{
    unsigned char const * const  b = static_cast<unsigned char const *>(
     buffer );
    process_block( b, b + byte_count );
    for(; byte_count; byte_count >>= 8)
        rem_ = (rem_ << 8) ^ crc_table_type::table_[((rem_ >> 24) ^ byte_count) & 0xFF];
}

通过这样的实现,该方法给出了与 相同的结果cksumfor循环由 GNU coreutils 提供。

希望我有所帮助。

于 2013-04-06T19:50:31.740 回答