设为首页 收藏本站
查看: 1402|回复: 0

[经验分享] Redis源码分析(十一)--- memtest内存检测

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2014-11-5 09:16:13 | 显示全部楼层 |阅读模式
今天我们继续redis源码test测试包下的其他文件,今天看完的是memtest文件,翻译器起来,就是memory test 内存检测的意思,这个文件虽然说代码量不是很多,但是里面的提及了很多东西,也给我涨了很多见识,网上关于memtest这种类似的redis内部边缘的文件解析基本没有,所以自己从头开始学习。机器的内存检测会和机器的CPU位数有关,32位或64位会影响后面的一些宏定义参数。首先亮出memtest中的API:



    /* 内存检测API */  
    void memtest_progress_start(char *title, int pass) /* 内存检测加载开始,输出开始的一些图线显示 */  
    void memtest_progress_end(void) /* progress bar加载完再次清屏操作 */  
    void memtest_progress_step(size_t curr, size_t size, char c) /* progress填充自己设置的字符串 */  
    void memtest_addressing(unsigned long *l, size_t bytes) /* 地址检测方法 */  
    void memtest_fill_random(unsigned long *l, size_t bytes) /* 随机填充内存 */  
    void memtest_fill_value(unsigned long *l, size_t bytes, unsigned long v1, unsigned long v2, char sym) /* 像上面的方法,只不过这是特定2种值的填充v1,v2 */  
    void memtest_compare(unsigned long *l, size_t bytes) /* 内存比较方法 */  
    void memtest_compare_times(unsigned long *m, size_t bytes, int pass, int times) /* 进行多次内存compare比较操作 */  
    void memtest_test(size_t megabytes, int passes) /* 整个内存检测类操作的测试方法,passes为目标的循环数 */  
    void memtest_non_destructive_invert(void *addr, size_t size) /* 将内存地址,进行了按位取反操作,不具有对数据的破坏性 */  
    void memtest_non_destructive_swap(void *addr, size_t size) /* 将内存地址,2个,2个内部之间做交换,同样不对数据具有破坏性 */  
    void memtest(size_t megabytes, int passes) /* 开发给整个系统使用的内存检测方法 */  


里面主要的方法就几个,每当一个内存检测的开始,都会出现progress bar的图线输出:



    /* 内存检测加载开始,输出开始的一些图线显示 */  
    void memtest_progress_start(char *title, int pass) {  
        int j;  
         
        /*这里其实包含2个命令,"\xlb[H","xlb[2j",后面的命令是主要的操作
         *"\x1b" 是ESC的16进制ASCII码值,这里也可经表示成八进制的\033,
         *[是一个CSI(Control sequence introducer),转义序列的作用由最后一个字符决定的,
         *这里J表示删除,默认情况下它删除从当前光标处到行尾的内容,
         *这里的2为参数,它表示删除所有的显示内容。也可以使用printf "\x1b[2J"。*/  
        //现定位home最开始的位置,然后实现请屏幕操作  
        printf("\x1b[H\x1b[2J");    /* Cursor home, clear screen. */  
              
        /* Fill with dots. */  
        /* 输出.符号填充屏幕 */  
        for (j = 0; j < ws.ws_col*(ws.ws_row-2); j++) printf(".");  
        printf("Please keep the test running several minutes per GB of memory.\n");  
        printf("Also check http://www.memtest86.com/ and http://pyropus.ca/software/memtester/");  
        //最后一个参数变了,为K,意义也不一样了变成删除当前行操作  
        printf("\x1b[H\x1b[2K");          /* Cursor home, clear current line.  */  
        printf("%s [%d]\n", title, pass); /* Print title. */  
        progress_printed = 0;  
        //求出填满progress bar所需点的个数  
        progress_full = ws.ws_col*(ws.ws_row-3);  
        fflush(stdout);  
    }  


我在里面解释了一下清屏操作的,printf输出形式。内存地址有效性的核心方法;



    /* Test that addressing is fine. Every location is populated with its own
     * address, and finally verified. This test is very fast but may detect
     * ASAP big issues with the memory subsystem. */  
    /* 此方法是测试内存地址是否有效,此种检测的速度是非常快的,但可能会检测出ASAP的巨大问题 */  
    /* ASAP网上查了下:(可能为)Automated Statistical Analysis Programme 自动统计分析程序 */  
    void memtest_addressing(unsigned long *l, size_t bytes) {  
        //算出地址的长度  
        unsigned long words = bytes/sizeof(unsigned long);  
        unsigned long j, *p;  
      
        /* Fill */  
        p = l;  
        for (j = 0; j < words; j++) {  
            //将(unsigned long)p强制类型转换到此时的*p,后面以此来判断,没有转换成功,说明存在内存地址的问题  
            *p = (unsigned long)p;  
            p++;  
            //用A字符填充部分progress bar  
            if ((j & 0xffff) == 0) memtest_progress_step(j,words*2,'A');  
        }  
        /* Test */  
        p = l;  
        for (j = 0; j < words; j++) {  
            //比较Address的关键在于  
            if (*p != (unsigned long)p) {  
                printf("\n*** MEMORY ADDRESSING ERROR: %p contains %lu\n",  
                    (void*) p, *p);  
                exit(1);  
            }  
            p++;  
            if ((j & 0xffff) == 0) memtest_progress_step(j+words,words*2,'A');  
        }  
    }  

为什么这样的方法去检测,本人也是带着比较疑惑的感觉。在内存检测中,内存地址有效性的检查只是其中的一个方法,还有一个是内存地址的填充测试,分为随机填充,和给定值的填充。下面给出随机填充的方法实现:



    /* Fill words stepping a single page at every write, so we continue to
     * touch all the pages in the smallest amount of time reducing the
     * effectiveness of caches, and making it hard for the OS to transfer
     * pages on the swap. */  
    /* 在每次写操作的时候,在单页上填满整个字符,这样可以做到最快速的触及所有的页面 */  
    /* 减少了低效率的缓存使用,但是会让分区在转移页面时会比较困难 */  
    /* 随机填充内存 */  
    void memtest_fill_random(unsigned long *l, size_t bytes) {  
        unsigned long step = 4096/sizeof(unsigned long);  
        unsigned long words = bytes/sizeof(unsigned long)/2;  
        unsigned long iwords = words/step;  /* words per iteration */  
        unsigned long off, w, *l1, *l2;  
      
        assert((bytes & 4095) == 0);  
        for (off = 0; off < step; off++) {  
            l1 = l+off;  
            l2 = l1+words;  
            for (w = 0; w < iwords; w++) {  
                //下面的rand()达到了随机存储的目的  
    #ifdef MEMTEST_32BIT  
                *l1 = *l2 = ((unsigned long)     (rand()&0xffff)) |  
                            (((unsigned long)    (rand()&0xffff)) << 16);  
    #else  
                *l1 = *l2 = ((unsigned long)     (rand()&0xffff)) |  
                            (((unsigned long)    (rand()&0xffff)) << 16) |  
                            (((unsigned long)    (rand()&0xffff)) << 32) |  
                            (((unsigned long)    (rand()&0xffff)) << 48);  
    #endif  
                l1 += step;  
                l2 += step;  
                if ((w & 0xffff) == 0)  
                    memtest_progress_step(w+iwords*off,words,'R');  
            }  
        }  
    }  


填充内存的好处是访问页面速度更快,不会出现断断续续的内存片,但是做页面交换的时候,由于没有空间,效率恐怕会比较低下。给定数值的填充与上面的类似,不展开说了。那么,内存测试程序到底是测哪些东西的呢,也就是说,他这个文件开放给外部的一个最直接的test方法是什么呢?



    /* 整个内存检测类操作的测试方法,passes为目标的循环数 */  
    void memtest_test(size_t megabytes, int passes) {  
        size_t bytes = megabytes*1024*1024;  
        unsigned long *m = malloc(bytes);  
        int pass = 0;  
      
        if (m == NULL) {  
            fprintf(stderr,"Unable to allocate %zu megabytes: %s",  
                megabytes, strerror(errno));  
            exit(1);  
        }  
         
        //必须经过passes论循环测试  
        while (pass != passes) {  
            pass++;  
      
            //地址检测  
            memtest_progress_start("Addressing test",pass);  
            memtest_addressing(m,bytes);  
            memtest_progress_end();  
      
            //随机填充检测  
            memtest_progress_start("Random fill",pass);  
            memtest_fill_random(m,bytes);  
            memtest_progress_end();  
            //填充后比较四次  
            memtest_compare_times(m,bytes,pass,4);  
      
            //给定数值填充,这里称为Solid fill固态填充  
            memtest_progress_start("Solid fill",pass);  
            memtest_fill_value(m,bytes,0,(unsigned long)-1,'S');  
            memtest_progress_end();  
            //填充后比较四次  
            memtest_compare_times(m,bytes,pass,4);  
              
            //也是属于给定数值填充,这里叫Checkerboard fill键盘填充  
            memtest_progress_start("Checkerboard fill",pass);  
            memtest_fill_value(m,bytes,ULONG_ONEZERO,ULONG_ZEROONE,'C');  
            memtest_progress_end();  
            //填充后比较四次  
            memtest_compare_times(m,bytes,pass,4);  
        }  
        free(m);  
    }  


可以看见,分为4中情况,1内存地址测试,2,3,4都为填充测试,分为3种类型的填充Random fill, Solid fill, Checkboard fill 。填充之后再做内存比较,这里的内存比较是在内存内部做前半部分的内存和后半部分的内存比较操作。在memtest文件的最后,提到了一个这样的方法:



    /* 开发给整个系统使用的内存检测方法 */  
    void memtest(size_t megabytes, int passes) {  
        if (ioctl(1, TIOCGWINSZ, &ws) == -1) {  
            ws.ws_col = 80;  
            ws.ws_row = 20;  
        }  
        memtest_test(megabytes,passes);  
        printf("\nYour memory passed this test.\n");  
        printf("Please if you are still in doubt use the following two tools:\n");  
        printf("1) memtest86: http://www.memtest86.com/\n");  
        printf("2) memtester: http://pyropus.ca/software/memtester/\n");  
        exit(0);  
    }  


这里提到了memtester和memtest86,上网查了一下,大体如下:

* * memtest和memtest86是2款内存检测软件
* memtest不但可以彻底的检测出内存的稳定度,还可同时测试记忆的储存与检索数据的能力,让你可以确实掌控到目前你机器上正在使用的内存到底可不可信赖。
* MemTest是一个绿色软件,直接点击执行文件即可运行
* memtest86这是一款小巧而专业的内存测试程序,是在著名的内存测试软件Memtest86基础上开发的。
* Memtest86+的安装和使用和其它内存测试软件有些不同,因为他不能在Windows下运行。
* 不过还是有四种方式可以运行此程序,分别为ISO引导盘、Linux下使用的bin文件、
* USB启动盘使用的EXE文件和软盘引导制作包。由于Memtest86+测试耗时较长,因此它不仅可以用于内存测试,还可以用于系统稳定性测试。Memtest86+测试完毕后,
* 按下“Esc”键退出并重新启动系统。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-27090-1-1.html 上篇帖子: Redis源码分析(十)--- testhelp.h小型测试框架和redis-check-aof.c日志检测 下篇帖子: Redis源码分析(十二)--- redis-check-dump本地数据库检测 检测
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

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