crc32 算法与实现

原文 :http://blog.sina.com.cn/s/blog_715691110102wqbr.html


crc就是一个数值,该数值用于检验数据的正确性,crc校验的原理就是将需要作校验的数据与一个数据模2相除,得到的余数即为校验值。

      模2相除就是在除的过程中用模2加,模2加实际上就是异或运算,就是不进行进位操作,即相同为假,不相同为真。

下面是几种CRC校验的生成多项式:

CRC8 = X8+X5+X4+1

CRC-CCITT = X16+X12+X5+1

CRC16=X16+X15+X2+1

CRC12=X12+X11+X3+X2+1

CRC32=X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X+1

一个多项式就是一个比特流,也就是由0、1组合起来的一组数

我们需要获取的常数就是上面多项式所对应的反转多项式(反转多项式:在数据通讯时,信息字节先传送或接受低位字节,如重新排列则影响速度)。

 

下面使用查表法实现crc校验,具体步骤如下:

(1)将上次计算出的CRC校验码右移一个字节;
(2)将移出的这个字节与新的要校验的字节进行XOR 运算;
(3)用运算出的值在预先生成码表中进行索引,获取对应的值(称为余式);
(4)用获取的值与第(1)步右移后的值进行XOR 运算;
(5)如果要校验的数据已经处理完,则第(4)步的结果就是最终的CRC校验码。如果还有数据要进行处理,则再转到第(1)步运行。


本例使用crc32校验,使用上面crc32的生成多项式,值为0xEDB88320

首先写一个功能函数,实现生成一个crc表,然后写一个功能函数,用于计算crc值,最后再写一个函数用于比较crc值,下面是全部代码:


  1. #include  
  2. #include  
  3. #include  
  4. #include  
  5.   
  6. uint32_t crc32_table[256];  
  7.   
  8. int make_crc32_table()  
  9.  
  10.     uint32_t c;  
  11.     int 0;  
  12.     int bit 0;  
  13.       
  14.     for(i 0; 256; i++)  
  15.      
  16.          (uint32_t)i;  
  17.           
  18.         for(bit 0; bit 8; bit++)  
  19.          
  20.             if(c&1)  
  21.              
  22.                 (c >> 1)^(0xEDB88320);  
  23.              
  24.             else  
  25.              
  26.                  >> 1;  
  27.              
  28.               
  29.          
  30.         crc32_table[i] c;  
  31.      
  32.       
  33.   
  34.  
  35.   
  36. uint32_t make_crc(uint32_t crc, unsigned char *string, uint32_t size)  
  37.  
  38.   
  39.     while(size--)  
  40.         crc (crc >> 8)^(crc32_table[(crc *string++)&0xff]);  
  41.   
  42.     return crc;  
  43.  
  44.   
  45. void compare_crc(char *filename)  
  46.  
  47.     FILE *sp NULL;  
  48.     uint32_t srcCrc  
  49.     uint32_t calcuCrc 0xffffffff;  
  50.     unsigned char buf[1024];  
  51.     uint32_t count;  
  52.       
  53.     if(filename == NULL)  
  54.      
  55.         printf("filename is null\n");  
  56.         exit(1);  
  57.      
  58.   
  59.     sp fopen(filename, "rb");  
  60.     if(sp == NULL)  
  61.      
  62.         printf("open file fail\n");  
  63.         exit(1);  
  64.      
  65.   
  66.     fread(&srcCrc, 1, 4, sp);  
  67.     printf("In %s: src crc is 0x%x\n"__FUNCTION__, srcCrc);     
  68.   
  69.   
  70.         if(sp)  
  71.          
  72.                 while(!feof(sp))  
  73.                  
  74.                         memset(buf, 0, sizeof(buf));  
  75.                         count fread(buf, 1, sizeof(buf), sp);  
  76.                         calcuCrc make_crc(calcuCrc, buf, count);  
  77.                  
  78.          
  79.     printf("In %s: calcuCrc is 0x%x\n"__FUNCTION__, calcuCrc);  
  80.   
  81.     fclose(sp);  
  82.   
  83.     if(srcCrc == calcuCrc)  
  84.      
  85.         printf("In %s: the calculate crc equal the src crc in file \n"__FUNCTION__);  
  86.   
  87.      
  88.     else  
  89.      
  90.         printf("In %s: the calculate crc not equal the src crc in file \n"__FUNCTION__);  
  91.      
  92.       
  93.  
  94.   
  95.   
  96. int main()  
  97.  
  98.     int i;  
  99.     FILE *sp NULL;  
  100.     FILE *dp NULL;  
  101.     uint32_t count;  
  102.     uint32_t crc 0xFFFFFFFF;  
  103.     unsigned char buf[1024];  
  104.       
  105.   
  106.     make_crc32_table();  
  107.   
  108.     sp fopen("/home/user/work_soft/crc_check/bak/test.txt""rb");  
  109.     if(sp == NULL)  
  110.      
  111.         printf("open file error\n");  
  112.         return -1;  
  113.      
  114.     dp fopen("/home/user/work_soft/crc_check/bak/testcrc.txt""wb");  
  115.     if(dp == NULL)  
  116.      
  117.         printf("open file error\n");  
  118.         return -1;  
  119.      
  120.   
  121.     if(sp)  
  122.      
  123.         while(!feof(sp))  
  124.          
  125.             memset(buf, 0, sizeof(buf));  
  126.             count fread(buf, 1, sizeof(buf), sp);  
  127.             crc make_crc(crc, buf, count);          
  128.          
  129.      
  130.   
  131.     printf("In main: calculate crc is 0x%x\n"crc);  
  132.     if(dp)  
  133.      
  134.         fwrite(&crc, 1, 4, dp);//write the crc into the file testcrc.txt  
  135.         fseek(sp, 0, SEEK_SET);  
  136.         while(!feof(sp))  
  137.          
  138.             memset(buf, 0, sizeof(buf));  
  139.                         count fread(buf, 1, sizeof(buf), sp);  
  140.             fwrite(buf, 1, count, dp);  
  141.          
  142.           
  143.         fclose(sp);  
  144.         fclose(dp);  
  145.      
  146.   
  147.       
  148.     compare_crc("/home/user/work_soft/crc_check/bak/testcrc.txt");  
  149.       
  150.   
  151.     return 0;  
  152.   
  153. }  

上面代码是根据查表法实现的,首先生成crc表,make_crc32_table就是根据crc校验的原理实现的,对0-255进行模2除法生成crc表;

函数make_crc是根据查表法的步骤实现的;而函数compare_crc则用来打开一个在头部嵌入crc值的文件,首先将文件头部的crc值取出(若用于功能实现,可设计一个数据结构用于存放crc等相关值,并存放在文件的头部),然后再读取文件的余下内容进行

crc计算,将计算出的crc值与从文件中读出的crc值进行比较,若相等则说明文件内容没有出错。下面是运行结果:




如果要将crc嵌入到文件头部,比如将计算得出的crc嵌入到升级文件的头部,由于我们生成的crc值的存储方式可能会因为不同的主机而不同(大端或小端)

所以在将crc值嵌入到升级文件的头部时,最好再加一个字节用于说明crc值得存储方式是大端还是小端模式,这样接收方就可以选择同一个存储方式,来确定读取的crc值是正确的

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值