设为首页收藏本站

EPS数据狗论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 1226|回复: 0

SQL SERVER数据页checksum校验算法

[复制链接]

38

主题

328

金钱

536

积分

初级用户

发表于 2019-6-12 13:42:33 | 显示全部楼层 |阅读模式

在SQL SERVER2005以上版本中,数据页默认开启checksum,标识为m_flagBits & 0x200 == True,其值m_tornBits位于页头0x3C,4字节。
其算法概述如下:
  1. 读8KB 进BUF
  2. 将BUF头部 CHECKSUM的4字节值清0
  3. uint32 checksum = 0 //初始checksum
  4. for i in range(0,15):
  5.          //每扇区的初始checksum
  6.          overall = 0;
  7.         for ii in range(0,127):
  8.                  //对当前扇区的每个4字节做累加异或
  9.                 overall = overall ^ BUF[i][ii];
  10.                 //对每扇区的checksum进行移位,方法为向左移位15-i位,
  11.                 //左边移出的15-i位补到最低位。
  12.                 checksum = checksum ^ rol(overall, 15- i);
  13. return checksum; //Gets checksum
复制代码

c源码如下:
  1. //***CODE***//
  2. #include <stdio.h>
  3. #include <stdlib.h>

  4. #define seed 15 //Initial seed(for first sector)
  5. #define CHAR_BIT 8

  6. //***PROTOTYPES***//
  7. unsigned int page_checksum(int page_id, unsigned int *ondisk);
  8. unsigned int rol(unsigned int value, unsigned int rotation);

  9. int main(int argc, char *argv[]) {

  10.     unsigned int computed_checksum; //Var to retrieve calculated checksum
  11.     unsigned int ondisk_checksum; //Var to retrieve checksum on disk

  12.         computed_checksum = page_checksum(152, &ondisk_checksum); //page_checksum call to retrieve stored and calculated checksum for page 152

  13.         //***PRINTS***//
  14.         printf("Calculated checksum: 0x%08x\n", computed_checksum);
  15.         printf("On disk checksum: 0x%08x\n", ondisk_checksum);

  16. }

  17. unsigned int page_checksum(int page_id, unsigned int *ondisk)
  18. {

  19.     FILE *fileptr;
  20.     unsigned int i;
  21.     unsigned int j;
  22.     unsigned int checksum;
  23.     unsigned int overall;
  24.     unsigned int *pagebuf[16][128]; //A pointer to describe 2d array [sector][element]

  25.     fileptr = fopen("C:\\Users\\andre\\Desktop\\teste.mdf", "r+b"); //Open dummy data file for binary read

  26.     fseek(fileptr, page_id * 8192, SEEK_SET); //Calculate page address on data file and points to it

  27.     fread(pagebuf, 4, 2048, fileptr); //Read page buffer

  28.     fclose(fileptr);

  29.     checksum = 0;
  30.     overall = 0;

  31.     *ondisk = pagebuf[0][15]; //This means that torn bits is stored on first sector in 15th element, Internals researches understand this

  32.     pagebuf[0][15] = 0x00000000; //Fill checksum field with zeroes (this field will be discarded in algorithm)

  33.     for (i = 0; i < 16; i++) //Loop through sectors
  34.     {

  35.         overall = 0; //Reset overall sum for sectors

  36.         for (j = 0; j < 128; j++) //Loop through elements in sector i
  37.         {
  38.             overall = overall ^ (unsigned int)pagebuf[i][j]; //XOR operation between sector i elements
  39.         }

  40.         checksum = checksum ^ rol(overall, seed - i); //Current checksum is overall for sector i circular shifted by seed (15 - i)
  41.     }

  42.     return checksum; //Gets checksum

  43. }

  44. unsigned int rol(unsigned int value, unsigned int rotation)
  45. {
  46.     return (value) << (rotation) | (value) >> (sizeof(int) * CHAR_BIT - rotation) & ( (1 << rotation) -1);
  47. }
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

客服中心
关闭
在线时间:
周一~周五
8:30-17:30
QQ群:
653541906
联系电话:
010-85786021-8017
在线咨询
客服中心

意见反馈|网站地图|手机版|小黑屋|EPS数据狗论坛 ( 京ICP备09019565号-3 )   

Powered by BFIT! X3.4

© 2008-2028 BFIT Inc.

快速回复 返回顶部 返回列表