校验,是在数据传送过程中为了检查数据完整性的一种手段。通常的做法是发送方在数据帧之中或者之后附带一段校验码,接收方通过特定的方式对接收到的所有数据做某种操作,操作的结果与预定的不符,说明传送中发生了错误,而有些校验码还附带纠错功能,即检查出错误后还可以恢复原数据,不过这种恢复是建立在一些假设基础上的,因此在实际大量数据传输中并不经常使用。
首先介绍distance的概念,distance就是两个N位码之间不同的位的个数。例如0110100与0111010,他们有3个位不同,distance就为3。
所有校验码的原理都是一样的:即从选取一个集合,这个集合中任意2个码的distance要大于m。只用这个集合中的元素传输数据,如果接收方接受到的数据不属于此集合,说明有错误在传输中发生。上面说的校验码就是为了达到这个目的。
如大家最熟悉最简单的奇偶校验,通过添加一个校验位,合法码集合的任意2个码的distance大于2,即1个合法码至少要改变2个位才能得到另一个合法码。
一个最小distance为m的集合,可以检测最多m-1位错误的传输,若有m位错误,就会被当作合法码而校验成功,还拿奇偶校验做例子,如果发生了2个位都因错误改变了(如1011变为1000),奇偶校验后还是合法的。
再说一个奇偶校验的衍生,就是累加和校验。奇偶校验的算法可以描述为:我们对一个数据帧按位相加,所得的结果作为校验位。类似的,我们讲数据1byte1byte的相加,无视溢出,就得到累加和校验byte。当然,并不一定必须要1byte1byte相加,这取决于处理器的位数,用16位机你也可以用2byte做累加和。
海明校验:distance=3,即可以校验2位错误
海明校验的基本思想是把数据分组,分别对每个组做奇偶校验。通过一系列规则的确定检查并且改正错误
分组规则:海明校验用bit1,bit2,bit4,bit8,bit16,bit32.......做为校验位,插到数据帧里面。这里的bit1,bit2指的是将校验位插入后,从低位到高位进行编号,从1开始编。例如发送01010010111(高位在前),则其中最末位1(bit1),次末位1(bit2),以及0(bit4),1(bit8),就是校验位。
由于校验位是2的倍数,因此校验位的编码都只含有1个1,如bit1=bit0001,bit2=bit0010,bit4=bit0100,bit8=bit1000.......那么,我们把所有与之对应位是1的分在一组,如bit3=bit0011,bit5=bit0101,bit7=bit0111,bit9=bit1001,bit11=bit1011,bit13=bit1101,bit15=bit1111这些最低位都为1,因此与bit1校验位分在同一组。对这组做奇校验或者偶校验,决定bit1的值。
bit7 bit6 bit5 bit3 bit4 bit2 bit1
1 0 1 0
1 0 0 1
1 1 0 0
这是一个7位数据的例子,bit7,6,5与bit4分为一组;bit7,6,3与bit2分为一组;bit7,5,3与bit1分为一组;对每行做偶校验,即可决定bit4,bit2,bit1的值
下面看下海明校验怎样纠错,在实际传输中,两位都发生错误的几率比一位发生错误的几率高很多,我们假设只有1位发生错误,如:
bit7 bit6 bit5 bit3 bit4 bit2 bit1
1 0 1 1
1 0 0 0
1 1 0 0
可以看出,第一行与第二行不满足偶校验规则,而能够引起这一结果的只有可能是bit6在传输中发生了错误,因为只有bit6对且仅对这两行产生效果。我们将bit6取反 就可得到未出错的数据
CRC校验,cyclic redundancy check 循环冗余码校验 。这种校验被广泛用于数据传输之中,因为它的纠错率很高,你的硬盘上,每512个字节后就会有一个CRC校验码,但是大部分人可能都不知道CRC校验的原理,这是我研究好久才得出的结论,网上绝对找不到的。
CRC校验的原理很简单:任何一个数位异或它本身,就得到全0。下面我们看一下CRC是如何产生校验码的。先介绍一下生成多项式的概念,一个多项式可以由一段二进制代码表示,如x3+x2+1可以用1101来表示,即1*x3+1*x2+0*x1+1*x0(次方我打不出来。。。)数据传送中,接受方和发送方先约定一个生成多项式(你可以在各种通信协议中找到,例如CRC-ITU,CRC-16,CRC-12等等),用数据帧左移N位后所代表的多项式除以NN+1位的生成多项式,就可得到N位的余式,这个余式代表的二进制序列就作为CRC校验码。这里的多项式除法和我们一般的除法有一些不同,大家不要深究,但是有除法的概念会对以后查表算法的理解有很到的帮助,所以在这里介绍一下。
那么怎么进行这种除法呢?比如数据帧为1011,生成多项式为11011,以生成4位CRC,首先把数据帧左移4位成10110000,写在被除数的位置,然后和11011首位对齐,做位异或:
10110000
11011
01101000(结果)
将11011右移直到上一步结果的左数第一个1与11011首位对齐,继续做位异或,直到结果为4位或以下
01101000
011011
00000100
则4位CRC就为0100
将来我们发送的数据就是10110100,将CRC附在数据帧后面。
很奇妙的是:把这个发送数据按上述规律再做同样的位异或操作,得到必定是全0,(原理会在以后讲到)大家可以笔算一下。这就是CRC检查错误的方法,CRC也有纠错功能,如果得到结果不是全0,则还按上述规则继续位异或,我们会发现余数是按某个规律循环的,这也是循环冗余码校验之所以得名的原因,直到出现某个特殊的余数时,可以证明出错位此时对应的就是出错位。但在实际中大量数据传输这种纠错能力很少应用,这里就不详细介绍了。
欢迎光临 (http://www.51hei.com/bbs/) | Powered by Discuz! X3.1 |